alshabib
Committed by Gerrit Code Review

Adding mfwd, igmp and mfwd apps

Change-Id: Ie7187716db36b754e4cd687a8f9de004e27c7825

adding mfwd, pim, igmp apps

Change-Id: Iddd2dcee24dc905d5ff0efe1d1d798fc83a7c736
Showing 32 changed files with 2742 additions and 0 deletions
......@@ -331,6 +331,7 @@ public class DhcpManagerTest {
@Override
public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) {
}
@Override
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.4.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-igmp</artifactId>
<packaging>bundle</packaging>
<description>Internet Group Message Protocol</description>
<properties>
<onos.app.name>org.onosproject.igmp</onos.app.name>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<scope>test</scope>
</dependency>
<!-- This is needed by ComponentContext, used for tunable configuration -->
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.9.8</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.slf4j,
org.osgi.framework,
org.apache.commons.lang.math.*,
com.google.common.*,
org.onlab.packet.*,
org.onlab.rest.*,
org.onosproject.*,
org.onosproject.mfwd.impl.*;
org.onlab.util.*,
org.jboss.netty.util.*
</Import-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.igmp.impl;
import static org.slf4j.LoggerFactory.getLogger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.IGMP;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.slf4j.Logger;
/**
* Internet Group Management Protocol.
*/
@Component(immediate = true)
public class IGMPComponent {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
private IGMPPacketProcessor processor = new IGMPPacketProcessor();
private static ApplicationId appId;
@Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.igmp");
packetService.addProcessor(processor, PacketProcessor.director(1));
// Build a traffic selector for all multicast traffic
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);
selector.matchIPProtocol(IPv4.PROTOCOL_IGMP);
packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
log.info("Started");
}
@Deactivate
public void deactivate() {
packetService.removeProcessor(processor);
processor = null;
log.info("Stopped");
}
/**
* Packet processor responsible for handling IGMP packets.
*/
private class IGMPPacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
// Stop processing if the packet has been handled, since we
// can't do any more to it.
if (context.isHandled()) {
return;
}
InboundPacket pkt = context.inPacket();
Ethernet ethPkt = pkt.parsed();
if (ethPkt == null) {
return;
}
/*
* IPv6 MLD packets are handled by ICMP6. We'll only deal
* with IPv4.
*/
if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
return;
}
IPv4 ip = (IPv4) ethPkt.getPayload();
IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
log.debug("Packet (" + saddr.toString() + ", " + gaddr.toString() +
"\tingress port: " + context.inPacket().receivedFrom().toString());
if (ip.getProtocol() != IPv4.PROTOCOL_IGMP) {
log.error("IGMP Picked up a non IGMP packet.");
return;
}
IpPrefix mcast = IpPrefix.valueOf("224.0.0.0/4");
if (!mcast.contains(gaddr)) {
log.error("IGMP Picked up a non multicast packet.");
return;
}
if (mcast.contains(saddr)) {
log.error("IGMP Picked up a packet with a multicast source address.");
return;
}
IpPrefix spfx = IpPrefix.valueOf(saddr, 32);
IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32);
IGMP igmp = (IGMP) ip.getPayload();
switch (igmp.getIgmpType()) {
case IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT:
IGMPProcessMembership.processMembership(igmp, pkt.receivedFrom());
break;
case IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY:
IGMPProcessQuery.processQuery(igmp, pkt.receivedFrom());
break;
case IGMP.TYPE_IGMPV1_MEMBERSHIP_REPORT:
case IGMP.TYPE_IGMPV2_MEMBERSHIP_REPORT:
case IGMP.TYPE_IGMPV2_LEAVE_GROUP:
log.debug("IGMP version 1 & 2 message types are not currently supported. Message type: " +
igmp.getIgmpType());
break;
default:
log.debug("Unkown IGMP message type: " + igmp.getIgmpType());
break;
}
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.igmp.impl;
import org.onlab.packet.IGMP;
import org.onosproject.net.ConnectPoint;
/**
* Process an IGMP Membership Report.
*/
public final class IGMPProcessMembership {
// Hide the default constructor.
private IGMPProcessMembership() {
}
/**
* Process the IGMP Membership report.
*
* @param igmp the deserialized IGMP message.
*/
public static void processMembership(IGMP igmp, ConnectPoint recievedFrom) {
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.igmp.impl;
import org.onlab.packet.IGMP;
import org.onosproject.net.ConnectPoint;
/**
* Process IGMP Query messages.
*/
public final class IGMPProcessQuery {
// Hide the default constructor.
private IGMPProcessQuery() {
}
/**
* Process the IGMP Membership Query message.
*
* @param igmp The deserialzed IGMP message
*/
public static void processQuery(IGMP igmp, ConnectPoint receivedFrom) {
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.4.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-mfwd</artifactId>
<packaging>bundle</packaging>
<description>Multicast forwarding application</description>
<properties>
<onos.app.name>org.onosproject.mfwd</onos.app.name>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
<version>3.9.0.Final</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<_wab>src/main/webapp/</_wab>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.slf4j,
org.osgi.framework,
javax.ws.rs,javax.ws.rs.core,
com.sun.jersey.api.core,
com.sun.jersey.spi.container.servlet,
com.sun.jersey.server.impl.container.servlet,
com.fasterxml.jackson.databind,
com.fasterxml.jackson.databind.node,
org.apache.commons.lang.math.*,
com.google.common.*,
org.onlab.packet.*,
org.onlab.rest.*,
org.onosproject.*,
org.onlab.util.*,
org.jboss.netty.util.*
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2014-2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.cli;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.mfwd.impl.McastRouteTable;
/**
* Delete a multicast route.
*/
@Command(scope = "onos", name = "mcast-delete",
description = "Delete a multicast route flow")
public class McastDeleteCommand extends AbstractShellCommand {
@Argument(index = 0, name = "sAddr",
description = "IP Address of the multicast source. '*' can be used for any source (*, G) entry",
required = true, multiValued = false)
String sAddr = null;
@Argument(index = 1, name = "gAddr",
description = "IP Address of the multicast group",
required = true, multiValued = false)
String gAddr = null;
@Override
protected void execute() {
McastRouteTable mrib = McastRouteTable.getInstance();
mrib.removeRoute(sAddr, gAddr);
}
}
/*
* Copyright 2014-2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.cli;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.packet.IpPrefix;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.mfwd.impl.McastRouteBase;
import org.onosproject.mfwd.impl.McastRouteTable;
/**
* Installs a source, multicast group flow.
*/
@Command(scope = "onos", name = "mcast-join",
description = "Installs a source, multicast group flow")
public class McastJoinCommand extends AbstractShellCommand {
@Argument(index = 0, name = "sAddr",
description = "IP Address of the multicast source. '*' can be used for any source (*, G) entry",
required = true, multiValued = false)
String sAddr = null;
@Argument(index = 1, name = "gAddr",
description = "IP Address of the multicast group",
required = true, multiValued = false)
String gAddr = null;
@Argument(index = 2, name = "ingressPort",
description = "Ingress port and Egress ports",
required = false, multiValued = false)
String ingressPort = null;
@Argument(index = 3, name = "ports",
description = "Ingress port and Egress ports",
required = false, multiValued = true)
String[] ports = null;
@Override
protected void execute() {
McastRouteTable mrib = McastRouteTable.getInstance();
IpPrefix mcast = IpPrefix.valueOf("224.0.0.0/4");
IpPrefix saddr = IpPrefix.valueOf(sAddr);
if (mcast.contains(saddr)) {
print("Error: the source address " + sAddr + " must be an IPv4 unicast address");
return;
}
IpPrefix gaddr = IpPrefix.valueOf(gAddr);
if (!mcast.contains(gaddr)) {
print("Error: " + gAddr + " must be a multicast group address");
return;
}
McastRouteBase mr = mrib.addRoute(sAddr, gAddr);
if (mr == null) {
print("Error: unable to save the multicast state");
return;
}
// Port format "of:0000000000000023/4"
if (ingressPort != null) {
String inCP = ingressPort;
log.debug("Ingress port provided: " + inCP);
String [] cp = inCP.split("/");
mr.addIngressPoint(cp[0], Long.parseLong(cp[1]));
} else {
return;
}
if (ports == null) {
return;
}
for (int i = 0; i < ports.length; i++) {
String egCP = ports[i];
log.debug("Egress port provided: " + egCP);
String [] cp = egCP.split("/");
mr.addEgressPoint(cp[0], Long.parseLong(cp[1]));
}
print("Added the mcast route");
}
}
/*
* Copyright 2014-2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.cli;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.ConnectPoint;
import org.onlab.packet.IpPrefix;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.onosproject.mfwd.impl.McastRouteTable;
import org.onosproject.mfwd.impl.McastRouteGroup;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Displays the source, multicast group flows entries.
*/
@Command(scope = "onos", name = "mcast-show", description = "Displays the source, multicast group flows")
public class McastShowCommand extends AbstractShellCommand {
private final Logger log = getLogger(getClass());
@Override
protected void execute() {
McastRouteTable mrt = McastRouteTable.getInstance();
if (outputJson()) {
print("%s", json(mrt));
} else {
printMrib4(mrt);
}
}
public JsonNode json(McastRouteTable mrt) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
Map<IpPrefix, McastRouteGroup> mrib4 = mrt.getMrib4();
for (McastRouteGroup mg : mrib4.values()) {
String sAddr = "";
String gAddr = "";
String inPort = "";
String outPorts = "";
if (mg.getSaddr() != null) {
sAddr = mg.getSaddr().toString();
log.info("Multicast Source: " + sAddr);
}
if (mg.getGaddr() != null) {
gAddr = mg.getGaddr().toString();
log.info("Multicast Group: " + gAddr);
}
if (mg.getIngressPoint() != null) {
inPort = mg.getIngressPoint().toString();
log.info("Multicast Ingress: " + inPort);
}
Set<ConnectPoint> eps = mg.getEgressPoints();
if (eps != null && !eps.isEmpty()) {
outPorts = eps.toString();
}
result.add(mapper.createObjectNode()
.put("src", sAddr)
.put("grp", gAddr)
.put("inPort", inPort)
.put("outPorts", outPorts));
}
return result;
}
/**
* Displays multicast route table entries.
*
* @param mrt route table
*/
protected void printMrib4(McastRouteTable mrt) {
print(mrt.printMcastRouteTable());
}
}
/**
* Sample Multicast forwarding framework using intents.
*/
package org.onosproject.mfwd.cli;
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.impl;
import static org.slf4j.LoggerFactory.getLogger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IPv4;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.slf4j.Logger;
/**
* WORK-IN-PROGRESS: The multicast forwarding application using intent framework.
*/
@Component(immediate = true)
public class McastForwarding {
private final Logger log = getLogger(getClass());
private final IpPrefix mcast = IpPrefix.valueOf("224.0.0.0/4");
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
private ReactivePacketProcessor processor = new ReactivePacketProcessor();
private McastRouteTable mrib;
private static ApplicationId appId;
/**
* Active MulticastForwardingIntent.
*/
@Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.mfwd");
packetService.addProcessor(processor, PacketProcessor.director(2));
// Build a traffic selector for all multicast traffic
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);
selector.matchIPDst(mcast);
packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
mrib = McastRouteTable.getInstance();
log.info("Started");
}
/**
* Deactivate Multicast Forwarding Intent.
*/
@Deactivate
public void deactivate() {
packetService.removeProcessor(processor);
processor = null;
log.info("Stopped");
}
/**
* Get the application ID, used by the McastIntentManager.
*
* @return the application ID
*/
public static ApplicationId getAppId() {
return appId;
}
/**
* Packet processor responsible for forwarding packets along their paths.
*/
private class ReactivePacketProcessor implements PacketProcessor {
/**
* Process incoming packets.
*
* @param context packet processing context
*/
@Override
public void process(PacketContext context) {
// Stop processing if the packet has been handled, since we
// can't do any more to it.
if (context.isHandled()) {
return;
}
InboundPacket pkt = context.inPacket();
Ethernet ethPkt = pkt.parsed();
if (ethPkt == null) {
return;
}
if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4 &&
ethPkt.getEtherType() != Ethernet.TYPE_IPV6) {
return;
}
if (ethPkt.getEtherType() == Ethernet.TYPE_IPV6) {
// Ignore ipv6 at the moment.
return;
}
IPv4 ip = (IPv4) ethPkt.getPayload();
IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
log.debug("Packet ({}, {}) has been punted\n" +
"\tingress port: {}\n",
saddr.toString(),
gaddr.toString(),
context.inPacket().receivedFrom().toString());
if (!mcast.contains(gaddr)) {
// Yikes, this is a bad group address
return;
}
if (mcast.contains(saddr)) {
// Yikes, the source address is multicast
return;
}
IpPrefix spfx = IpPrefix.valueOf(saddr, 32);
IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32);
/*
* Do a best match lookup on the (s, g) of the packet. If an entry does
* not exist create one and store it's incoming connect point.
*
* The connect point is deviceId / portId that the packet entered
* the SDN network. This differs from traditional mcast where the
* ingress port would be a specific device.
*/
McastRoute entry = mrib.findBestMatch(spfx, gpfx);
if (entry == null || entry.getSaddr().equals(IPv4.fromIPv4Address(0))) {
/*
* Create an entry that we can fast drop.
*/
entry = mrib.addRoute(spfx, gpfx);
entry.addIngressPoint(context.inPacket().receivedFrom());
}
/*
* TODO: If we do not have an ingress or any egress connect points we
* should set up a fast drop entry.
*/
if (entry.getIngressPoint() == null) {
return;
}
if (entry.getEgressPoints().isEmpty()) {
return;
}
/*
* This is odd, we should not have received a punted packet if an
* intent was installed unless the intent was not installed
* correctly. However, we are seeing packets get punted after
* the intent has been installed.
*
* Therefore we are going to forward the packets even if they
* should have already been forwarded by the intent fabric.
*/
if (entry.getIntentKey() != null) {
return;
}
entry.setIntent();
McastIntentManager im = McastIntentManager.getInstance();
im.setIntent(entry);
entry.incrementPuntCount();
// Send the pack out each of the egress devices & port
forwardPacketToDst(context, entry);
}
}
/**
* Forward the packet to it's multicast destinations.
*
* @param context The packet context
* @param entry The multicast route entry matching this packet
*/
private void forwardPacketToDst(PacketContext context, McastRoute entry) {
// Send the pack out each of the respective egress ports
for (ConnectPoint egress : entry.getEgressPoints()) {
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(egress.port()).build();
OutboundPacket packet = new DefaultOutboundPacket(
egress.deviceId(),
treatment,
context.inPacket().unparsed());
packetService.emit(packet);
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
@Component(immediate = true)
@Service(value = org.onosproject.mfwd.impl.McastIntentManager.class)
public class McastIntentManager {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
private static McastIntentManager instance;
public McastIntentManager() {
instance = this;
}
/**
* Active this component.
*/
@Activate
public void activate() { }
/**
* Deactivate this component.
*/
@Deactivate
public void deactivate() {
withdrawAllIntents();
}
/**
* Get instance of this intentManager.
*
* @return the instance of this intent manager.
*/
public static McastIntentManager getInstance() {
if (instance == null) {
instance = new McastIntentManager();
}
return instance;
}
/**
* Install the PointToMultipoint forwarding intent.
*
* @param mroute multicast route entry
* @return the intent that has been set or null otherwise
*/
public SinglePointToMultiPointIntent setIntent(McastRoute mroute) {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
if (mroute.getIngressPoint() == null ||
mroute.getEgressPoints().isEmpty()) {
return null;
}
/*
* Match the group AND source addresses. We will also check ether type to
* determine if we are doing ipv4 or ipv6.
*
* If we really wanted to be pendantic we could put in a
* condition to make sure the ethernet MAC address was also
* mcast.
*/
selector.matchEthType(Ethernet.TYPE_IPV4)
.matchIPDst(mroute.getGaddr())
.matchIPSrc(mroute.getSaddr());
SinglePointToMultiPointIntent intent =
SinglePointToMultiPointIntent.builder()
.appId(McastForwarding.getAppId())
.selector(selector.build())
.treatment(treatment)
.ingressPoint(mroute.getIngressPoint())
.egressPoints(mroute.getEgressPoints()).
build();
intentService.submit(intent);
return intent;
}
/**
* Withdraw the intent represented by this route.
*
* @param mroute the mcast route whose intent we want to remove
*/
public void withdrawIntent(McastRouteBase mroute) {
Intent intent = intentService.getIntent(mroute.getIntentKey());
intentService.withdraw(intent);
}
/**
* Withdraw all intents.
*
* This will be called from the deactivate method so we don't leave
* a mess behind us after we leave.
*/
public void withdrawAllIntents() {
for (Intent intent : intentService.getIntents()) {
intentService.withdraw(intent);
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.impl;
import org.onlab.packet.IpPrefix;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import java.util.Set;
/**
* This McastRouteBase interface is implemented by the McastRouteBase class which
* in turn acts as the base class for both the McastRouteGroup and McastRouteSource.
*/
interface McastRoute {
/**
* Gets the group addresses.
*
* @return group address
*/
public IpPrefix getGaddr();
/**
* Gets the source address.
*
* @return the source address
*/
public IpPrefix getSaddr();
/**
* Determines if this is an IPv4 multicast route.
*
* @return true if it is an IPv4 route
*/
public boolean isIp4();
/**
* Determines if this is an IPv6 multicast route.
*
* @return true if it is an IPv6 route
*/
public boolean isIp6();
/**
* Add the ingress ConnectPoint with a ConnectPoint.
*
* @param ingress ingress point
*/
public void addIngressPoint(ConnectPoint ingress);
/**
* Add the ingress Connect Point using. ..
*
* @param deviceId device ID
* @param portNum port number
*/
public void addIngressPoint(String deviceId, long portNum);
/**
* Get the ingress connect point.
*
* @return the ingress connect point
*/
public ConnectPoint getIngressPoint();
/**
* Add an egress connect point.
*
* @param member the egress ConnectPoint to be added
*/
public void addEgressPoint(ConnectPoint member);
/**
* Add an egress connect point.
*
* @param deviceId the device ID of the connect point
* @param portNum the port number of the connect point
*/
public void addEgressPoint(String deviceId, long portNum);
/**
* Get the egress connect points.
*
* @return a set of egress connect points
*/
public Set<ConnectPoint> getEgressPoints();
/**
* Increment the punt count.
*/
public void incrementPuntCount();
/**
* Get the punt count.
*
* @return the punt count
*/
public int getPuntCount();
/**
* Have the McastIntentManager create an intent, attempt to
* install the intent and then save the key.
*/
public void setIntent();
/**
* Set the Intent key.
*
* @param intent intent
*/
public void setIntent(SinglePointToMultiPointIntent intent);
/**
* Withdraw the intent if it has been installed.
*/
public void withdrawIntent();
/**
* Get the intent key.
*
* @return the intentKey
*/
public Key getIntentKey();
/**
* Pretty print the the route.
*
* @return a pretty string
*/
public String toString();
}
\ No newline at end of file
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import org.onlab.packet.IpPrefix;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import org.onosproject.net.intent.Key;
import java.util.Set;
import java.util.HashSet;
/**
* McastRouteBase base class for McastRouteGroup and McastRouteSource.
*/
public class McastRouteBase implements McastRoute {
protected final IpPrefix gaddr;
protected final IpPrefix saddr;
protected ConnectPoint ingressPoint;
protected Set<ConnectPoint> egressPoints;
protected boolean isGroup = false;
/**
* How may times has this packet been punted.
*/
private int puntCount = 0;
/**
* If the intentKey is null that means no intent has
* been installed.
*/
protected Key intentKey = null;
/**
* Create a multicast route. This is the parent class for both the Group
* and the source.
*
* @param saddr source address
* @param gaddr multicast group address
*/
public McastRouteBase(String saddr, String gaddr) {
this.gaddr = IpPrefix.valueOf(checkNotNull(gaddr));
if (saddr == null || saddr.equals("*")) {
this.saddr = IpPrefix.valueOf(0, 0);
} else {
this.saddr = IpPrefix.valueOf(checkNotNull(gaddr));
}
this.init();
}
/**
* Create a multicast group table entry.
* @param gaddr multicast group address
*/
public McastRouteBase(String gaddr) {
this("*", gaddr);
}
/**
* Set the source and group address value of a (*, G) group.
*
* @param gpfx the group prefix address
*/
public McastRouteBase(IpPrefix gpfx) {
this(IpPrefix.valueOf(0, 0), gpfx);
}
/**
* Create a multicast route constructor.
*
* @param saddr source address
* @param gaddr group address
*/
public McastRouteBase(IpPrefix saddr, IpPrefix gaddr) {
this.saddr = checkNotNull(saddr);
this.gaddr = checkNotNull(gaddr);
this.init();
}
private void init() {
this.isGroup = (this.saddr.prefixLength() == 0);
this.ingressPoint = null;
this.egressPoints = new HashSet();
}
/**
* Get the multicast group address.
*
* @return the multicast group address
*/
@Override
public IpPrefix getGaddr() {
return gaddr;
}
/**
* Get the multicast source address.
*
* @return the multicast source address
*/
@Override
public IpPrefix getSaddr() {
return saddr;
}
/**
* Is this an IPv4 multicast route.
*
* @return true if it is an IPv4 route
*/
@Override
public boolean isIp4() {
return gaddr.isIp4();
}
/**
* Is this an IPv6 multicast route.
*
* @return true if it is an IPv6 route
*/
@Override
public boolean isIp6() {
return gaddr.isIp6();
}
/**
* Is this a multicast group route?
*
* @return true if it is a multicast group route.
*/
public boolean isGroup() {
return isGroup;
}
/**
* @return true if this is (S, G) false if it (*, G).
*/
public boolean isSource() {
return (!isGroup);
}
/**
* Add an ingress point to this route.
*
* @param ingress incoming connect point
*/
@Override
public void addIngressPoint(ConnectPoint ingress) {
ingressPoint = checkNotNull(ingress);
}
/**
* Add or modify the ingress connect point.
*
* @param deviceId the switch device Id
* @param portNum the ingress port number
*/
@Override
public void addIngressPoint(String deviceId, long portNum) {
ingressPoint = new ConnectPoint(
DeviceId.deviceId(deviceId),
PortNumber.portNumber(portNum));
}
/**
* Get the ingress ConnectPoint.
*
* @return the ingress ConnectPoint
*/
@Override
public ConnectPoint getIngressPoint() {
return this.ingressPoint;
}
/**
* Add an egress ConnectPoint.
*
* @param member member egress connect point
*/
@Override
public void addEgressPoint(ConnectPoint member) {
egressPoints.add(checkNotNull(member));
}
/**
* Add an egress ConnectPoint.
*
* @param deviceId deviceId of the connect point
* @param portNum portNum of the connect point
*/
@Override
public void addEgressPoint(String deviceId, long portNum) {
ConnectPoint cp = new ConnectPoint(DeviceId.deviceId(deviceId), PortNumber.portNumber(portNum));
this.egressPoints.add(cp);
}
/**
* Get egress connect points for the route.
*
* @return Set of egress connect points
*/
@Override
public Set<ConnectPoint> getEgressPoints() {
return egressPoints;
}
/**
* Get the number of times the packet has been punted.
*
* @return the punt count
*/
@Override
public int getPuntCount() {
return puntCount;
}
/**
* Increment the punt count.
*
* TODO: we need to handle wrapping.
*/
@Override
public void incrementPuntCount() {
puntCount++;
}
/**
* Have the McastIntentManager create and set the intent, then save the intent key.
*
* If we already have an intent, we will first withdraw the existing intent and
* replace it with a new one. This will support the case where the ingress connectPoint
* or group of egress connectPoints change.
*/
@Override
public void setIntent() {
if (this.intentKey != null) {
this.withdrawIntent();
}
McastIntentManager im = McastIntentManager.getInstance();
SinglePointToMultiPointIntent intent = im.setIntent(this);
this.intentKey = intent.key();
}
/**
* Set the Intent key.
*
* @param intent intent
*/
@Override
public void setIntent(SinglePointToMultiPointIntent intent) {
intentKey = intent.key();
}
/**
* Get the intent key represented by this route.
*
* @return intentKey
*/
@Override
public Key getIntentKey() {
return this.intentKey;
}
/**
* Withdraw the intent and set the key to null.
*/
@Override
public void withdrawIntent() {
if (intentKey == null) {
// nothing to withdraw
return;
}
McastIntentManager im = McastIntentManager.getInstance();
im.withdrawIntent(this);
this.intentKey = null;
}
/**
* Pretty Print this Multicast Route. Works for McastRouteSource and McastRouteGroup.
*
* @return pretty string of the multicast route
*/
@Override
public String toString() {
String out = String.format("(%s, %s)\n\t",
saddr.toString(), gaddr.toString());
out += "intent: ";
out += (intentKey == null) ? "not installed" : this.intentKey.toString();
out += "\n\tingress: ";
out += (ingressPoint == null) ? "NULL" : ingressPoint.toString();
out += "\n\tegress: {\n";
if (egressPoints != null && !egressPoints.isEmpty()) {
for (ConnectPoint eg : egressPoints) {
out += "\t\t" + eg.toString() + "\n";
}
}
out += ("\t}\n");
out += ("\tpunted: " + this.getPuntCount() + "\n");
return out;
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.HashMap;
import org.onlab.packet.IpPrefix;
/**
* The McastRouteGroup extends the McastRouteBase class and serves two purposes:
* first it represents a (*, G) multicast route entry. Second it serves
* as a container for all (S, G) multicast route entries that belong
* to the same group address.
*/
public class McastRouteGroup extends McastRouteBase {
private HashMap<IpPrefix, McastRouteSource> sources;
/**
* Class constructor.
*
* @param gaddr - String representation of group address.
*/
public McastRouteGroup(String gaddr) {
super(checkNotNull(gaddr));
this.init();
}
/**
* Create a multicast group.
*
* @param gpfx - Group address
*/
public McastRouteGroup(IpPrefix gpfx) {
super(checkNotNull(gpfx));
this.init();
}
/**
* Common initialization used by constructors.
*/
private void init() {
this.sources = new HashMap();
super.isGroup = true;
}
/**
* Find a specific multicast source address for this group.
*
* @param saddr the source address
* @return the multicast source route or null if it does not exist
*/
public McastRouteSource findSource(IpPrefix saddr) {
return this.sources.get(checkNotNull(saddr));
}
/**
* Return the entire set of multicast sources for this group.
*
* @return the set of multicast sources
*/
public HashMap<IpPrefix, McastRouteSource> getSources() {
return this.sources;
}
/**
* Add a new McastRouteSource to this group.
*
* @param src the multicast source
*/
public void addSource(McastRouteSource src) {
checkNotNull(src);
this.sources.put(src.getSaddr(), src);
}
/**
* Remove the source with this specific IpPrefix from this group entry.
*
* @param spfx IP Prefix of the source to be removed
* @return the source route that was just removed
*/
public McastRouteSource removeSource(IpPrefix spfx) {
McastRouteSource src = this.sources.remove(spfx);
src.withdrawIntent();
return src;
}
/**
* Remove all sources from this.
*/
public void removeSources() {
for (McastRouteSource src : this.sources.values()) {
src.withdrawIntent();
this.sources.remove(src.getSaddr());
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import org.onlab.packet.IpPrefix;
/**
* This class represents and specific multicast senders source address. Objects from
* this class will belong to the sources collection of the multicast group.
*/
public class McastRouteSource extends McastRouteBase {
// A reference to our parent group
private McastRouteGroup group;
/**
* Create a multicast source with IpPrefixes.
*
* @param source the source address
* @param group the group address
*/
public McastRouteSource(IpPrefix source, IpPrefix group) {
super(checkNotNull(source), checkNotNull(group));
}
/**
* Set our parent multicast group.
*
* @param group the group this source belongs to
*/
public void setGroup(McastRouteGroup group) {
this.group = group;
}
}
\ No newline at end of file
/**
* Sample Multicast forwarding framework using intents.
*/
package org.onosproject.mfwd.impl;
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.mfwd.rest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.onlab.packet.IpPrefix;
import org.onlab.rest.BaseResource;
import org.onosproject.mfwd.impl.McastRouteGroup;
import org.onosproject.mfwd.impl.McastRouteTable;
/**
* Rest API for Multicast Forwarding.
*/
@Path("mcast")
public class McastResource extends BaseResource {
/**
* Retrieve the multicast route table.
* @return the multicast route table.
* @throws IOException if an error occurs
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response showAll() throws IOException {
ObjectMapper mapper = new ObjectMapper();
McastRouteTable mcastRouteTable = McastRouteTable.getInstance();
Map<IpPrefix, McastRouteGroup> map = mcastRouteTable.getMrib4();
return Response.ok(mapper.createObjectNode().toString()).build();
}
/**
* Static join of a multicast flow.
* @param input source, group, ingress connectPoint egress connectPoints
* @return status of static join
* @throws IOException if an error occurs
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response join(InputStream input) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode cfg = mapper.readTree(input);
return null;
}
}
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.mfwd.cli.McastJoinCommand"/>
</command>
<command>
<action class="org.onosproject.mfwd.cli.McastDeleteCommand"/>
</command>
<command>
<action class="org.onosproject.mfwd.cli.McastShowCommand"/>
</command>
</command-bundle>
</blueprint>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="ONOS" version="2.5">
<display-name>ONOS APP MFWD</display-name>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.classnames</param-name>
<param-value>
org.onosproject.mfwd.rest.McastResource
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.4.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-pim</artifactId>
<packaging>bundle</packaging>
<description>Protocol Independent Multicast Emulation</description>
<properties>
<onos.app.name>org.onosproject.pim</onos.app.name>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<scope>test</scope>
</dependency>
<!-- This is needed by ComponentContext, used for tunable configuration -->
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.9.8</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.slf4j,
org.osgi.framework,
org.apache.commons.lang.math.*,
com.google.common.*,
org.onlab.packet.*,
org.onlab.rest.*,
org.onosproject.*,
org.onosproject.mfwd.impl.*;
org.onlab.util.*,
org.jboss.netty.util.*
</Import-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2014-2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pim.cli;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.ConnectPoint;
import org.onosproject.pim.impl.PIMNeighbors;
import org.onosproject.pim.impl.PIMNeighborsCodec;
import java.util.HashMap;
@Command(scope = "onos", name = "pim-show", description = "Displays the pim neighbors")
public class PIMShowCommand extends AbstractShellCommand {
// prints either the json or cli version of the hash map connect point
// neighbors from the PIMNeighbors class.
@Override
protected void execute() {
// grab connect point neighbors hash map to send in to json encoder.
HashMap<ConnectPoint, PIMNeighbors> pimNbrs = PIMNeighbors.getConnectPointNeighbors();
if (outputJson()) {
print("%s", json(pimNbrs));
} else {
print(PIMNeighbors.printPimNeighbors());
}
}
private JsonNode json(HashMap<ConnectPoint, PIMNeighbors> pimNbrs) {
return new PIMNeighborsCodec().encode(pimNbrs, this);
}
}
\ No newline at end of file
/**
* PIM Multicast forwarding framework using intents.
*/
package org.onosproject.pim.cli;
\ No newline at end of file
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pim.impl;
import static org.slf4j.LoggerFactory.getLogger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.PIM;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.slf4j.Logger;
/**
* Protocol Independent Multicast Emulation.
*/
@Component(immediate = true)
public class PIMComponent {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
private PIMPacketProcessor processor = new PIMPacketProcessor();
private static ApplicationId appId;
@Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.pim");
packetService.addProcessor(processor, PacketProcessor.director(1));
// Build a traffic selector for all multicast traffic
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);
selector.matchIPProtocol(IPv4.PROTOCOL_PIM);
packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
log.info("Started");
}
@Deactivate
public void deactivate() {
packetService.removeProcessor(processor);
processor = null;
log.info("Stopped");
}
/**
* Packet processor responsible for handling IGMP packets.
*/
private class PIMPacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
// Stop processing if the packet has been handled, since we
// can't do any more to it.
if (context.isHandled()) {
return;
}
InboundPacket pkt = context.inPacket();
if (pkt == null) {
return;
}
Ethernet ethPkt = pkt.parsed();
if (ethPkt == null) {
return;
}
/*
* IPv6 MLD packets are handled by ICMP6. We'll only deal
* with IPv4.
*/
if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
return;
}
IPv4 ip = (IPv4) ethPkt.getPayload();
IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
log.debug("Packet (" + saddr.toString() + ", " + gaddr.toString() +
"\tingress port: " + context.inPacket().receivedFrom().toString());
if (ip.getProtocol() != IPv4.PROTOCOL_PIM) {
log.debug("PIM Picked up a non PIM packet: IP protocol: " + ip.getProtocol());
return;
}
// TODO: check incoming to be PIM.PIM_ADDRESS or "Our" address.
IpPrefix spfx = IpPrefix.valueOf(saddr, 32);
IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32);
PIM pim = (PIM) ip.getPayload();
switch (pim.getPimMsgType()) {
case PIM.TYPE_HELLO:
PIMNeighbors.processHello(ethPkt, context.inPacket().receivedFrom());
break;
case PIM.TYPE_JOIN_PRUNE_REQUEST:
// Create the function
break;
case PIM.TYPE_ASSERT:
case PIM.TYPE_BOOTSTRAP:
case PIM.TYPE_CANDIDATE_RP_ADV:
case PIM.TYPE_GRAFT:
case PIM.TYPE_GRAFT_ACK:
case PIM.TYPE_REGISTER:
case PIM.TYPE_REGISTER_STOP:
log.debug("Unsupported PIM message type: " + pim.getPimMsgType());
break;
default:
log.debug("Unkown PIM message type: " + pim.getPimMsgType());
break;
}
}
}
}
/*
* Copyright 2014-2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in reliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pim.impl;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.TimerTask;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.pim.PIMHello;
import org.onlab.packet.pim.PIMHelloOption;
import org.onosproject.net.ConnectPoint;
import org.slf4j.Logger;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* PIMNeighbor represents all the PIM routers that have sent us
* hello messages, or that possibly have been statically configured.
*/
public class PIMNeighbor {
private final Logger log = getLogger(getClass());
// The primary address of this PIM neighbor
private IpAddress primaryAddr;
// The MacAddress of this neighbor
private MacAddress macAddress;
// The ConnectPoint this PIM neighbor is connected to.
private ConnectPoint connectPoint;
// Is this neighbor us?
private boolean isThisUs = false;
// The option values this neighbor has sent us.
private int priority = 0;
private int genId = 0;
private short holdtime = 0;
// Is this pim neighbor the DR?
private boolean isDr = false;
// Timeout for this neighbor
private volatile Timeout timeout;
private boolean reelect = false;
// A back pointer the neighbors list this neighbor belongs to.
private PIMNeighbors neighbors;
/**
* Construct this neighbor from the address and connect point.
*
* @param ipaddr IP Address of neighbor
* @param macaddr MAC Address of the neighbor
* @param cp The ConnectPoint of this neighbor
*/
public PIMNeighbor(IpAddress ipaddr, MacAddress macaddr, ConnectPoint cp) {
this.macAddress = macaddr;
this.primaryAddr = ipaddr;
this.connectPoint = cp;
this.resetTimeout();
}
/**
* Get the primary address of this neighbor.
*
* @return the primary IP address.
*/
public IpAddress getPrimaryAddr() {
return primaryAddr;
}
/**
* Set the primary address of this neighbor.
*
* @param primaryAddr the address we'll use when sending hello messages
*/
public void setPrimaryAddr(IpAddress primaryAddr) {
this.primaryAddr = primaryAddr;
}
/**
* Get the priority this neighbor has advertised to us.
*
* @return the priority
*/
public int getPriority() {
return priority;
}
/**
* Set the priority for this neighbor.
*
* @param priority This neighbors priority.
*/
public void setPriority(int priority) {
this.priority = priority;
}
/**
* Get the generation ID.
*
* @return the generation ID.
*/
public int getGenId() {
return genId;
}
/**
* Set the generation ID.
*
* @param genId the generation ID.
*/
public void setGenId(int genId) {
this.genId = genId;
}
/**
* Get the holdtime for this neighbor.
*
* @return the holdtime
*/
public short getHoldtime() {
return holdtime;
}
/**
* Set the holdtime for this neighbor.
*
* @param holdtime the holdtime.
*/
public void setholdtime(short holdtime) {
this.holdtime = holdtime;
}
/**
* Is this neighbor the designated router on this connect point?
*
* @return true if so, false if not.
*/
public boolean isDr() {
return isDr;
}
/**
* Set this router as the designated router on this connect point.
*
* @param isDr True is this neighbor is the DR false otherwise
*/
public void setIsDr(boolean isDr) {
this.isDr = isDr;
}
/**
* The ConnectPoint this neighbor is connected to.
*
* @return the ConnectPoint
*/
public ConnectPoint getConnectPoint() {
return connectPoint;
}
/**
* Set the ConnectPoint this router is connected to.
*
* @param connectPoint the ConnectPoint this router is connected to.
*/
public void setConnectPoint(ConnectPoint connectPoint) {
this.connectPoint = connectPoint;
}
/**
* Set a back pointer to the neighbors list this neighbor is a member of.
*
* @param neighbors the neighbor list this neighbor belongs to
*/
public void setNeighbors(PIMNeighbors neighbors) {
this.neighbors = neighbors;
}
/**
* We have received a fresh hello from a neighbor, now we need to process it.
* Depending on the values received in the the hello options may force a
* re-election process.
*
* We will also refresh the timeout for this neighbor.
*
* @param hello copy of the hello we'll be able to extract options from.
*/
public void refresh(PIMHello hello) {
checkNotNull(hello);
for (PIMHelloOption opt : hello.getOptions().values()) {
int len = opt.getOptLength();
byte [] value = new byte[len];
ByteBuffer bb = ByteBuffer.wrap(value);
switch (opt.getOptType()) {
case PIMHelloOption.OPT_GENID:
int newid = bb.getInt();
if (this.genId != newid) {
// TODO: we have a newly rebooted neighbor. Send them our joins.
this.genId = newid;
}
break;
case PIMHelloOption.OPT_PRIORITY:
int newpri = bb.getInt();
if (this.priority != newpri) {
// The priorities have changed. We may need to re-elect a new DR?
if (this.isDr || this.neighbors.getDesignatedRouter().getPriority() < priority) {
reelect = true;
}
this.priority = newpri;
}
break;
case PIMHelloOption.OPT_HOLDTIME:
short holdtime = bb.getShort();
if (this.holdtime != holdtime) {
this.holdtime = holdtime;
if (holdtime == 0) {
// We have a neighbor going down. We can remove all joins
// we have learned from them.
// TODO: What else do we need to do when a neighbor goes down?
log.debug("PIM Neighbor has timed out: {}", this.primaryAddr.toString());
return;
}
}
break;
case PIMHelloOption.OPT_PRUNEDELAY:
case PIMHelloOption.OPT_ADDRLIST:
// TODO: implement prune delay and addr list. Fall through for now.
default:
log.debug("PIM Hello option type: {} not yet supported or unknown.", opt.getOptType());
break;
}
}
if (reelect) {
this.neighbors.electDR(this);
}
// Reset the next timeout timer
this.resetTimeout();
}
/* --------------------------------------- Timer functions -------------------------- */
/**
* Restart the timeout task for this neighbor.
*/
private void resetTimeout() {
if (this.holdtime == 0) {
// Prepare to die.
log.debug("shutting down timer for nbr {}", this.primaryAddr.toString());
if (this.timeout != null) {
this.timeout.cancel();
this.timeout = null;
}
return;
}
// Cancel the existing timeout and start a fresh new one.
if (this.timeout != null) {
this.timeout.cancel();
}
this.timeout = PIMTimer.getTimer().newTimeout(new NeighborTimeoutTask(this), holdtime, TimeUnit.SECONDS);
}
/**
* The task to run when a neighbor timeout expires.
*/
private final class NeighborTimeoutTask implements TimerTask {
PIMNeighbor nbr;
NeighborTimeoutTask(PIMNeighbor nbr) {
this.nbr = nbr;
}
@Override
public void run(Timeout timeout) throws Exception {
// TODO: log.debug;
PIMNeighbors neighbors = nbr.neighbors;
neighbors.removeNeighbor(nbr.getPrimaryAddr());
}
}
/**
* Stop the timeout timer.
*
* This happens when we remove the neighbor.
*/
private final void stopTimeout() {
this.timeout.cancel();
this.timeout = null;
}
@Override
public String toString() {
String out = "";
if (this.isDr) {
out += "*NBR:";
} else {
out += "NBR:";
}
out += "\tIP: " + this.primaryAddr.toString();
out += "\tPr: " + String.valueOf(this.priority);
out += "\tHoldTime: " + String.valueOf(this.holdtime);
out += "\tGenID: " + String.valueOf(this.genId) + "\n";
return out;
}
}
\ No newline at end of file
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pim.impl;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.ConnectPoint;
import java.util.HashMap;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* PIM neighbors Codec.
*/
public class PIMNeighborsCodec extends JsonCodec<HashMap<ConnectPoint, PIMNeighbors>> {
// JSON field names
//Return Name
private static final String CPNBRLIST = "connect_point_list";
// PIM Neightbors Fields
private static final String IP = "ip";
private static final String PRIORITY = "priority";
private static final String NBRLIST = "neighbor_list";
// PIM neighbor Files
private static final String DR = "designated";
private static final String NBR_IP = "ip";
private static final String PR = "priority";
private static final String HOLDTIME = "hold_time";
/**
* Encode the PIM Neighbors.
*
* @param cpn ConnectPoint neighbors
* @param context encoding context
*
* @return Encoded neighbors used by CLI and REST
*/
@Override
public ObjectNode encode(HashMap<ConnectPoint, PIMNeighbors> cpn, CodecContext context) {
checkNotNull(cpn, "Pim Neighbors cannot be null");
ObjectNode pimNbrJsonCodec = context.mapper().createObjectNode();
ArrayNode cpnList = context.mapper().createArrayNode();
for (PIMNeighbors pn: cpn.values()) {
// get the PimNeighbors Obj, contains Neighbors list
// create the json object for a single Entry in the Neighbors list
ObjectNode cp = context.mapper().createObjectNode();
cp.put(IP, pn.getOurIpAddress().toString());
cp.put(PRIORITY, String.valueOf(pn.getOurPriority()));
// create the array for the neighbors list
ArrayNode nbrsList = context.mapper().createArrayNode();
for (PIMNeighbor nbr : pn.getOurNeighborsList().values()) {
nbrsList.add(neighbor(nbr, context));
}
// adds pim neighbor to list
cp.set(NBRLIST, nbrsList);
// adds to arraynode which will represent the connect point neighbors hash map.
cpnList.add(cp);
}
pimNbrJsonCodec.set(CPNBRLIST, cpnList);
return pimNbrJsonCodec;
}
/**
* Encode a single PIM Neighbor.
*
* @param nbr the neighbor to be encoded
* @param context encoding context
* @return the encoded neighbor
*/
private ObjectNode neighbor(PIMNeighbor nbr, CodecContext context) {
return context.mapper().createObjectNode()
.put(DR, Boolean.toString(nbr.isDr()))
.put(NBR_IP, nbr.getPrimaryAddr().toString())
.put(PR, String.valueOf(nbr.getPriority()))
.put(HOLDTIME, String.valueOf(nbr.getHoldtime()));
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pim.impl;
import org.jboss.netty.util.HashedWheelTimer;
/**
* PIM Timer used for PIM Neighbors.
*/
public final class PIMTimer {
private static volatile HashedWheelTimer timer;
// Ban public construction
private PIMTimer() {
}
/**
* Returns the singleton hashed-wheel timer.
*
* @return hashed-wheel timer
*/
public static HashedWheelTimer getTimer() {
if (PIMTimer.timer == null) {
initTimer();
}
return PIMTimer.timer;
}
// Start the PIM timer.
private static synchronized void initTimer() {
if (PIMTimer.timer == null) {
// Create and start a new hashed wheel timer, if it does not exist.
HashedWheelTimer hwTimer = new HashedWheelTimer();
hwTimer.start();
PIMTimer.timer = hwTimer;
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* PIM Emulation speak hello messages and listen to Join/Prunes.
*/
package org.onosproject.pim.impl;
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.pim.cli.PIMShowCommand"/>
</command>
</command-bundle>
</blueprint>
......@@ -58,6 +58,9 @@
<module>vtnweb</module>
<module>dhcp</module>
<module>cordvtn</module>
<module>mfwd</module>
<module>igmp</module>
<module>pim</module>
</modules>
<properties>
......