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 { | ... | @@ -331,6 +331,7 @@ public class DhcpManagerTest { |
331 | 331 | ||
332 | @Override | 332 | @Override |
333 | public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) { | 333 | public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) { |
334 | + | ||
334 | } | 335 | } |
335 | 336 | ||
336 | @Override | 337 | @Override | ... | ... |
apps/igmp/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2014 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
18 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
20 | + <modelVersion>4.0.0</modelVersion> | ||
21 | + | ||
22 | + <parent> | ||
23 | + <groupId>org.onosproject</groupId> | ||
24 | + <artifactId>onos-apps</artifactId> | ||
25 | + <version>1.4.0-SNAPSHOT</version> | ||
26 | + <relativePath>../pom.xml</relativePath> | ||
27 | + </parent> | ||
28 | + | ||
29 | + <artifactId>onos-app-igmp</artifactId> | ||
30 | + <packaging>bundle</packaging> | ||
31 | + | ||
32 | + <description>Internet Group Message Protocol</description> | ||
33 | + | ||
34 | + <properties> | ||
35 | + <onos.app.name>org.onosproject.igmp</onos.app.name> | ||
36 | + </properties> | ||
37 | + | ||
38 | + <dependencies> | ||
39 | + <dependency> | ||
40 | + <groupId>org.onosproject</groupId> | ||
41 | + <artifactId>onos-api</artifactId> | ||
42 | + <version>${project.version}</version> | ||
43 | + </dependency> | ||
44 | + | ||
45 | + <dependency> | ||
46 | + <groupId>org.onosproject</groupId> | ||
47 | + <artifactId>onos-cli</artifactId> | ||
48 | + <version>${project.version}</version> | ||
49 | + </dependency> | ||
50 | + | ||
51 | + | ||
52 | + <dependency> | ||
53 | + <groupId>org.onosproject</groupId> | ||
54 | + <artifactId>onlab-osgi</artifactId> | ||
55 | + <version>${project.version}</version> | ||
56 | + </dependency> | ||
57 | + | ||
58 | + <dependency> | ||
59 | + <groupId>org.onosproject</groupId> | ||
60 | + <artifactId>onlab-junit</artifactId> | ||
61 | + <scope>test</scope> | ||
62 | + </dependency> | ||
63 | + | ||
64 | + <!-- This is needed by ComponentContext, used for tunable configuration --> | ||
65 | + <dependency> | ||
66 | + <groupId>org.osgi</groupId> | ||
67 | + <artifactId>org.osgi.compendium</artifactId> | ||
68 | + </dependency> | ||
69 | + | ||
70 | + <dependency> | ||
71 | + <groupId>org.apache.felix</groupId> | ||
72 | + <artifactId>org.apache.felix.scr.annotations</artifactId> | ||
73 | + <version>1.9.8</version> | ||
74 | + <scope>provided</scope> | ||
75 | + </dependency> | ||
76 | + | ||
77 | + </dependencies> | ||
78 | + | ||
79 | + <build> | ||
80 | + <plugins> | ||
81 | + <plugin> | ||
82 | + <groupId>org.apache.felix</groupId> | ||
83 | + <artifactId>maven-bundle-plugin</artifactId> | ||
84 | + <extensions>true</extensions> | ||
85 | + <configuration> | ||
86 | + <instructions> | ||
87 | + <Bundle-SymbolicName> | ||
88 | + ${project.groupId}.${project.artifactId} | ||
89 | + </Bundle-SymbolicName> | ||
90 | + <Import-Package> | ||
91 | + org.slf4j, | ||
92 | + org.osgi.framework, | ||
93 | + org.apache.commons.lang.math.*, | ||
94 | + com.google.common.*, | ||
95 | + org.onlab.packet.*, | ||
96 | + org.onlab.rest.*, | ||
97 | + org.onosproject.*, | ||
98 | + org.onosproject.mfwd.impl.*; | ||
99 | + org.onlab.util.*, | ||
100 | + org.jboss.netty.util.* | ||
101 | + </Import-Package> | ||
102 | + </instructions> | ||
103 | + </configuration> | ||
104 | + </plugin> | ||
105 | + <plugin> | ||
106 | + <groupId>org.apache.maven.plugins</groupId> | ||
107 | + <artifactId>maven-compiler-plugin</artifactId> | ||
108 | + <version>2.5.1</version> | ||
109 | + <configuration> | ||
110 | + <source>1.8</source> | ||
111 | + <target>1.8</target> | ||
112 | + </configuration> | ||
113 | + </plugin> | ||
114 | + </plugins> | ||
115 | + </build> | ||
116 | + | ||
117 | +</project> |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.igmp.impl; | ||
17 | + | ||
18 | +import static org.slf4j.LoggerFactory.getLogger; | ||
19 | + | ||
20 | +import org.apache.felix.scr.annotations.Activate; | ||
21 | +import org.apache.felix.scr.annotations.Component; | ||
22 | +import org.apache.felix.scr.annotations.Deactivate; | ||
23 | +import org.apache.felix.scr.annotations.Reference; | ||
24 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
25 | +import org.onlab.packet.Ethernet; | ||
26 | +import org.onlab.packet.IPv4; | ||
27 | +import org.onlab.packet.Ip4Address; | ||
28 | +import org.onlab.packet.IpAddress; | ||
29 | +import org.onlab.packet.IpPrefix; | ||
30 | +import org.onlab.packet.IGMP; | ||
31 | +import org.onosproject.core.ApplicationId; | ||
32 | +import org.onosproject.core.CoreService; | ||
33 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
34 | +import org.onosproject.net.flow.TrafficSelector; | ||
35 | +import org.onosproject.net.packet.InboundPacket; | ||
36 | +import org.onosproject.net.packet.PacketContext; | ||
37 | +import org.onosproject.net.packet.PacketPriority; | ||
38 | +import org.onosproject.net.packet.PacketProcessor; | ||
39 | +import org.onosproject.net.packet.PacketService; | ||
40 | +import org.slf4j.Logger; | ||
41 | + | ||
42 | +/** | ||
43 | + * Internet Group Management Protocol. | ||
44 | + */ | ||
45 | +@Component(immediate = true) | ||
46 | +public class IGMPComponent { | ||
47 | + private final Logger log = getLogger(getClass()); | ||
48 | + | ||
49 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
50 | + protected PacketService packetService; | ||
51 | + | ||
52 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
53 | + protected CoreService coreService; | ||
54 | + | ||
55 | + private IGMPPacketProcessor processor = new IGMPPacketProcessor(); | ||
56 | + private static ApplicationId appId; | ||
57 | + | ||
58 | + @Activate | ||
59 | + public void activate() { | ||
60 | + appId = coreService.registerApplication("org.onosproject.igmp"); | ||
61 | + | ||
62 | + packetService.addProcessor(processor, PacketProcessor.director(1)); | ||
63 | + | ||
64 | + // Build a traffic selector for all multicast traffic | ||
65 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
66 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
67 | + selector.matchIPProtocol(IPv4.PROTOCOL_IGMP); | ||
68 | + packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId); | ||
69 | + | ||
70 | + log.info("Started"); | ||
71 | + } | ||
72 | + | ||
73 | + @Deactivate | ||
74 | + public void deactivate() { | ||
75 | + packetService.removeProcessor(processor); | ||
76 | + processor = null; | ||
77 | + log.info("Stopped"); | ||
78 | + } | ||
79 | + | ||
80 | + /** | ||
81 | + * Packet processor responsible for handling IGMP packets. | ||
82 | + */ | ||
83 | + private class IGMPPacketProcessor implements PacketProcessor { | ||
84 | + | ||
85 | + @Override | ||
86 | + public void process(PacketContext context) { | ||
87 | + // Stop processing if the packet has been handled, since we | ||
88 | + // can't do any more to it. | ||
89 | + if (context.isHandled()) { | ||
90 | + return; | ||
91 | + } | ||
92 | + | ||
93 | + InboundPacket pkt = context.inPacket(); | ||
94 | + Ethernet ethPkt = pkt.parsed(); | ||
95 | + if (ethPkt == null) { | ||
96 | + return; | ||
97 | + } | ||
98 | + | ||
99 | + /* | ||
100 | + * IPv6 MLD packets are handled by ICMP6. We'll only deal | ||
101 | + * with IPv4. | ||
102 | + */ | ||
103 | + if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) { | ||
104 | + return; | ||
105 | + } | ||
106 | + | ||
107 | + IPv4 ip = (IPv4) ethPkt.getPayload(); | ||
108 | + IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress()); | ||
109 | + IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress()); | ||
110 | + log.debug("Packet (" + saddr.toString() + ", " + gaddr.toString() + | ||
111 | + "\tingress port: " + context.inPacket().receivedFrom().toString()); | ||
112 | + | ||
113 | + if (ip.getProtocol() != IPv4.PROTOCOL_IGMP) { | ||
114 | + log.error("IGMP Picked up a non IGMP packet."); | ||
115 | + return; | ||
116 | + } | ||
117 | + | ||
118 | + IpPrefix mcast = IpPrefix.valueOf("224.0.0.0/4"); | ||
119 | + if (!mcast.contains(gaddr)) { | ||
120 | + log.error("IGMP Picked up a non multicast packet."); | ||
121 | + return; | ||
122 | + } | ||
123 | + | ||
124 | + if (mcast.contains(saddr)) { | ||
125 | + log.error("IGMP Picked up a packet with a multicast source address."); | ||
126 | + return; | ||
127 | + } | ||
128 | + IpPrefix spfx = IpPrefix.valueOf(saddr, 32); | ||
129 | + IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32); | ||
130 | + | ||
131 | + IGMP igmp = (IGMP) ip.getPayload(); | ||
132 | + switch (igmp.getIgmpType()) { | ||
133 | + | ||
134 | + case IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT: | ||
135 | + IGMPProcessMembership.processMembership(igmp, pkt.receivedFrom()); | ||
136 | + break; | ||
137 | + | ||
138 | + case IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY: | ||
139 | + IGMPProcessQuery.processQuery(igmp, pkt.receivedFrom()); | ||
140 | + break; | ||
141 | + | ||
142 | + case IGMP.TYPE_IGMPV1_MEMBERSHIP_REPORT: | ||
143 | + case IGMP.TYPE_IGMPV2_MEMBERSHIP_REPORT: | ||
144 | + case IGMP.TYPE_IGMPV2_LEAVE_GROUP: | ||
145 | + log.debug("IGMP version 1 & 2 message types are not currently supported. Message type: " + | ||
146 | + igmp.getIgmpType()); | ||
147 | + break; | ||
148 | + | ||
149 | + default: | ||
150 | + log.debug("Unkown IGMP message type: " + igmp.getIgmpType()); | ||
151 | + break; | ||
152 | + } | ||
153 | + } | ||
154 | + } | ||
155 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.igmp.impl; | ||
17 | + | ||
18 | +import org.onlab.packet.IGMP; | ||
19 | +import org.onosproject.net.ConnectPoint; | ||
20 | + | ||
21 | +/** | ||
22 | + * Process an IGMP Membership Report. | ||
23 | + */ | ||
24 | +public final class IGMPProcessMembership { | ||
25 | + | ||
26 | + // Hide the default constructor. | ||
27 | + private IGMPProcessMembership() { | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * Process the IGMP Membership report. | ||
32 | + * | ||
33 | + * @param igmp the deserialized IGMP message. | ||
34 | + */ | ||
35 | + public static void processMembership(IGMP igmp, ConnectPoint recievedFrom) { | ||
36 | + } | ||
37 | + | ||
38 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.igmp.impl; | ||
17 | + | ||
18 | +import org.onlab.packet.IGMP; | ||
19 | +import org.onosproject.net.ConnectPoint; | ||
20 | + | ||
21 | +/** | ||
22 | + * Process IGMP Query messages. | ||
23 | + */ | ||
24 | +public final class IGMPProcessQuery { | ||
25 | + | ||
26 | + // Hide the default constructor. | ||
27 | + private IGMPProcessQuery() { | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * Process the IGMP Membership Query message. | ||
32 | + * | ||
33 | + * @param igmp The deserialzed IGMP message | ||
34 | + */ | ||
35 | + public static void processQuery(IGMP igmp, ConnectPoint receivedFrom) { | ||
36 | + } | ||
37 | + | ||
38 | +} |
apps/mfwd/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2014 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
18 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
20 | + <modelVersion>4.0.0</modelVersion> | ||
21 | + | ||
22 | + <parent> | ||
23 | + <groupId>org.onosproject</groupId> | ||
24 | + <artifactId>onos-apps</artifactId> | ||
25 | + <version>1.4.0-SNAPSHOT</version> | ||
26 | + <relativePath>../pom.xml</relativePath> | ||
27 | + </parent> | ||
28 | + | ||
29 | + <artifactId>onos-app-mfwd</artifactId> | ||
30 | + <packaging>bundle</packaging> | ||
31 | + | ||
32 | + <description>Multicast forwarding application</description> | ||
33 | + | ||
34 | + <properties> | ||
35 | + <onos.app.name>org.onosproject.mfwd</onos.app.name> | ||
36 | + </properties> | ||
37 | + | ||
38 | + <dependencies> | ||
39 | + <dependency> | ||
40 | + <groupId>org.onosproject</groupId> | ||
41 | + <artifactId>onos-cli</artifactId> | ||
42 | + <version>${project.version}</version> | ||
43 | + </dependency> | ||
44 | + <dependency> | ||
45 | + <groupId>io.netty</groupId> | ||
46 | + <artifactId>netty</artifactId> | ||
47 | + <version>3.9.0.Final</version> | ||
48 | + </dependency> | ||
49 | + | ||
50 | + <dependency> | ||
51 | + <groupId>org.osgi</groupId> | ||
52 | + <artifactId>org.osgi.compendium</artifactId> | ||
53 | + </dependency> | ||
54 | + | ||
55 | + <dependency> | ||
56 | + <groupId>org.apache.karaf.shell</groupId> | ||
57 | + <artifactId>org.apache.karaf.shell.console</artifactId> | ||
58 | + </dependency> | ||
59 | + | ||
60 | + <dependency> | ||
61 | + <groupId>org.osgi</groupId> | ||
62 | + <artifactId>org.osgi.core</artifactId> | ||
63 | + </dependency> | ||
64 | + | ||
65 | + <dependency> | ||
66 | + <groupId>org.onosproject</groupId> | ||
67 | + <artifactId>onlab-rest</artifactId> | ||
68 | + <version>${project.version}</version> | ||
69 | + </dependency> | ||
70 | + <dependency> | ||
71 | + <groupId>org.onosproject</groupId> | ||
72 | + <artifactId>onos-rest</artifactId> | ||
73 | + <version>${project.version}</version> | ||
74 | + </dependency> | ||
75 | + <dependency> | ||
76 | + <groupId>com.sun.jersey</groupId> | ||
77 | + <artifactId>jersey-servlet</artifactId> | ||
78 | + </dependency> | ||
79 | + <dependency> | ||
80 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
81 | + <artifactId>jackson-databind</artifactId> | ||
82 | + </dependency> | ||
83 | + <dependency> | ||
84 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
85 | + <artifactId>jackson-annotations</artifactId> | ||
86 | + </dependency> | ||
87 | + | ||
88 | + <dependency> | ||
89 | + <groupId>org.onosproject</groupId> | ||
90 | + <artifactId>onlab-junit</artifactId> | ||
91 | + <scope>test</scope> | ||
92 | + </dependency> | ||
93 | + | ||
94 | + <dependency> | ||
95 | + <groupId>org.easymock</groupId> | ||
96 | + <artifactId>easymock</artifactId> | ||
97 | + <scope>test</scope> | ||
98 | + </dependency> | ||
99 | + | ||
100 | + </dependencies> | ||
101 | + | ||
102 | + | ||
103 | + <build> | ||
104 | + <plugins> | ||
105 | + <plugin> | ||
106 | + <groupId>org.apache.felix</groupId> | ||
107 | + <artifactId>maven-bundle-plugin</artifactId> | ||
108 | + <extensions>true</extensions> | ||
109 | + <configuration> | ||
110 | + <instructions> | ||
111 | + <_wab>src/main/webapp/</_wab> | ||
112 | + <Bundle-SymbolicName> | ||
113 | + ${project.groupId}.${project.artifactId} | ||
114 | + </Bundle-SymbolicName> | ||
115 | + <Import-Package> | ||
116 | + org.slf4j, | ||
117 | + org.osgi.framework, | ||
118 | + javax.ws.rs,javax.ws.rs.core, | ||
119 | + com.sun.jersey.api.core, | ||
120 | + com.sun.jersey.spi.container.servlet, | ||
121 | + com.sun.jersey.server.impl.container.servlet, | ||
122 | + com.fasterxml.jackson.databind, | ||
123 | + com.fasterxml.jackson.databind.node, | ||
124 | + org.apache.commons.lang.math.*, | ||
125 | + com.google.common.*, | ||
126 | + org.onlab.packet.*, | ||
127 | + org.onlab.rest.*, | ||
128 | + org.onosproject.*, | ||
129 | + org.onlab.util.*, | ||
130 | + org.jboss.netty.util.* | ||
131 | + </Import-Package> | ||
132 | + <Web-ContextPath>${web.context}</Web-ContextPath> | ||
133 | + </instructions> | ||
134 | + </configuration> | ||
135 | + </plugin> | ||
136 | + </plugins> | ||
137 | + </build> | ||
138 | + | ||
139 | +</project> | ||
140 | + |
1 | +/* | ||
2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.cli; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Argument; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | + | ||
22 | +import org.onosproject.mfwd.impl.McastRouteTable; | ||
23 | + | ||
24 | +/** | ||
25 | + * Delete a multicast route. | ||
26 | + */ | ||
27 | +@Command(scope = "onos", name = "mcast-delete", | ||
28 | + description = "Delete a multicast route flow") | ||
29 | +public class McastDeleteCommand extends AbstractShellCommand { | ||
30 | + | ||
31 | + @Argument(index = 0, name = "sAddr", | ||
32 | + description = "IP Address of the multicast source. '*' can be used for any source (*, G) entry", | ||
33 | + required = true, multiValued = false) | ||
34 | + String sAddr = null; | ||
35 | + | ||
36 | + @Argument(index = 1, name = "gAddr", | ||
37 | + description = "IP Address of the multicast group", | ||
38 | + required = true, multiValued = false) | ||
39 | + String gAddr = null; | ||
40 | + | ||
41 | + @Override | ||
42 | + protected void execute() { | ||
43 | + McastRouteTable mrib = McastRouteTable.getInstance(); | ||
44 | + mrib.removeRoute(sAddr, gAddr); | ||
45 | + } | ||
46 | +} | ||
47 | + |
1 | +/* | ||
2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.cli; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Argument; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onlab.packet.IpPrefix; | ||
21 | +import org.onosproject.cli.AbstractShellCommand; | ||
22 | + | ||
23 | +import org.onosproject.mfwd.impl.McastRouteBase; | ||
24 | +import org.onosproject.mfwd.impl.McastRouteTable; | ||
25 | + | ||
26 | +/** | ||
27 | + * Installs a source, multicast group flow. | ||
28 | + */ | ||
29 | +@Command(scope = "onos", name = "mcast-join", | ||
30 | + description = "Installs a source, multicast group flow") | ||
31 | +public class McastJoinCommand extends AbstractShellCommand { | ||
32 | + | ||
33 | + @Argument(index = 0, name = "sAddr", | ||
34 | + description = "IP Address of the multicast source. '*' can be used for any source (*, G) entry", | ||
35 | + required = true, multiValued = false) | ||
36 | + String sAddr = null; | ||
37 | + | ||
38 | + @Argument(index = 1, name = "gAddr", | ||
39 | + description = "IP Address of the multicast group", | ||
40 | + required = true, multiValued = false) | ||
41 | + String gAddr = null; | ||
42 | + | ||
43 | + @Argument(index = 2, name = "ingressPort", | ||
44 | + description = "Ingress port and Egress ports", | ||
45 | + required = false, multiValued = false) | ||
46 | + String ingressPort = null; | ||
47 | + | ||
48 | + @Argument(index = 3, name = "ports", | ||
49 | + description = "Ingress port and Egress ports", | ||
50 | + required = false, multiValued = true) | ||
51 | + String[] ports = null; | ||
52 | + | ||
53 | + @Override | ||
54 | + protected void execute() { | ||
55 | + McastRouteTable mrib = McastRouteTable.getInstance(); | ||
56 | + IpPrefix mcast = IpPrefix.valueOf("224.0.0.0/4"); | ||
57 | + IpPrefix saddr = IpPrefix.valueOf(sAddr); | ||
58 | + if (mcast.contains(saddr)) { | ||
59 | + print("Error: the source address " + sAddr + " must be an IPv4 unicast address"); | ||
60 | + return; | ||
61 | + } | ||
62 | + | ||
63 | + IpPrefix gaddr = IpPrefix.valueOf(gAddr); | ||
64 | + if (!mcast.contains(gaddr)) { | ||
65 | + print("Error: " + gAddr + " must be a multicast group address"); | ||
66 | + return; | ||
67 | + } | ||
68 | + | ||
69 | + McastRouteBase mr = mrib.addRoute(sAddr, gAddr); | ||
70 | + if (mr == null) { | ||
71 | + print("Error: unable to save the multicast state"); | ||
72 | + return; | ||
73 | + } | ||
74 | + | ||
75 | + // Port format "of:0000000000000023/4" | ||
76 | + if (ingressPort != null) { | ||
77 | + String inCP = ingressPort; | ||
78 | + log.debug("Ingress port provided: " + inCP); | ||
79 | + String [] cp = inCP.split("/"); | ||
80 | + mr.addIngressPoint(cp[0], Long.parseLong(cp[1])); | ||
81 | + } else { | ||
82 | + return; | ||
83 | + } | ||
84 | + | ||
85 | + if (ports == null) { | ||
86 | + return; | ||
87 | + } | ||
88 | + | ||
89 | + for (int i = 0; i < ports.length; i++) { | ||
90 | + String egCP = ports[i]; | ||
91 | + log.debug("Egress port provided: " + egCP); | ||
92 | + String [] cp = egCP.split("/"); | ||
93 | + mr.addEgressPoint(cp[0], Long.parseLong(cp[1])); | ||
94 | + } | ||
95 | + print("Added the mcast route"); | ||
96 | + } | ||
97 | +} |
1 | +/* | ||
2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.cli; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Command; | ||
19 | +import org.onosproject.cli.AbstractShellCommand; | ||
20 | +import org.onosproject.net.ConnectPoint; | ||
21 | +import org.onlab.packet.IpPrefix; | ||
22 | + | ||
23 | +import java.util.Map; | ||
24 | +import java.util.Set; | ||
25 | + | ||
26 | +import org.slf4j.Logger; | ||
27 | +import org.onosproject.mfwd.impl.McastRouteTable; | ||
28 | +import org.onosproject.mfwd.impl.McastRouteGroup; | ||
29 | + | ||
30 | +import com.fasterxml.jackson.databind.JsonNode; | ||
31 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
32 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
33 | + | ||
34 | +import static org.slf4j.LoggerFactory.getLogger; | ||
35 | + | ||
36 | +/** | ||
37 | + * Displays the source, multicast group flows entries. | ||
38 | + */ | ||
39 | +@Command(scope = "onos", name = "mcast-show", description = "Displays the source, multicast group flows") | ||
40 | +public class McastShowCommand extends AbstractShellCommand { | ||
41 | + | ||
42 | + private final Logger log = getLogger(getClass()); | ||
43 | + | ||
44 | + @Override | ||
45 | + protected void execute() { | ||
46 | + McastRouteTable mrt = McastRouteTable.getInstance(); | ||
47 | + if (outputJson()) { | ||
48 | + print("%s", json(mrt)); | ||
49 | + } else { | ||
50 | + printMrib4(mrt); | ||
51 | + } | ||
52 | + } | ||
53 | + | ||
54 | + public JsonNode json(McastRouteTable mrt) { | ||
55 | + ObjectMapper mapper = new ObjectMapper(); | ||
56 | + ArrayNode result = mapper.createArrayNode(); | ||
57 | + Map<IpPrefix, McastRouteGroup> mrib4 = mrt.getMrib4(); | ||
58 | + for (McastRouteGroup mg : mrib4.values()) { | ||
59 | + String sAddr = ""; | ||
60 | + String gAddr = ""; | ||
61 | + String inPort = ""; | ||
62 | + String outPorts = ""; | ||
63 | + if (mg.getSaddr() != null) { | ||
64 | + sAddr = mg.getSaddr().toString(); | ||
65 | + log.info("Multicast Source: " + sAddr); | ||
66 | + } | ||
67 | + if (mg.getGaddr() != null) { | ||
68 | + gAddr = mg.getGaddr().toString(); | ||
69 | + log.info("Multicast Group: " + gAddr); | ||
70 | + } | ||
71 | + if (mg.getIngressPoint() != null) { | ||
72 | + inPort = mg.getIngressPoint().toString(); | ||
73 | + log.info("Multicast Ingress: " + inPort); | ||
74 | + } | ||
75 | + Set<ConnectPoint> eps = mg.getEgressPoints(); | ||
76 | + if (eps != null && !eps.isEmpty()) { | ||
77 | + outPorts = eps.toString(); | ||
78 | + } | ||
79 | + result.add(mapper.createObjectNode() | ||
80 | + .put("src", sAddr) | ||
81 | + .put("grp", gAddr) | ||
82 | + .put("inPort", inPort) | ||
83 | + .put("outPorts", outPorts)); | ||
84 | + } | ||
85 | + return result; | ||
86 | + } | ||
87 | + | ||
88 | + /** | ||
89 | + * Displays multicast route table entries. | ||
90 | + * | ||
91 | + * @param mrt route table | ||
92 | + */ | ||
93 | + protected void printMrib4(McastRouteTable mrt) { | ||
94 | + print(mrt.printMcastRouteTable()); | ||
95 | + } | ||
96 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.impl; | ||
17 | + | ||
18 | +import static org.slf4j.LoggerFactory.getLogger; | ||
19 | + | ||
20 | +import org.apache.felix.scr.annotations.Activate; | ||
21 | +import org.apache.felix.scr.annotations.Component; | ||
22 | +import org.apache.felix.scr.annotations.Deactivate; | ||
23 | +import org.apache.felix.scr.annotations.Reference; | ||
24 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
25 | + | ||
26 | +import org.onlab.packet.Ethernet; | ||
27 | +import org.onlab.packet.IpPrefix; | ||
28 | +import org.onlab.packet.IpAddress; | ||
29 | +import org.onlab.packet.Ip4Address; | ||
30 | +import org.onlab.packet.IPv4; | ||
31 | +import org.onosproject.core.ApplicationId; | ||
32 | +import org.onosproject.core.CoreService; | ||
33 | +import org.onosproject.net.ConnectPoint; | ||
34 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
35 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
36 | +import org.onosproject.net.flow.TrafficSelector; | ||
37 | +import org.onosproject.net.flow.TrafficTreatment; | ||
38 | +import org.onosproject.net.packet.DefaultOutboundPacket; | ||
39 | +import org.onosproject.net.packet.InboundPacket; | ||
40 | +import org.onosproject.net.packet.OutboundPacket; | ||
41 | +import org.onosproject.net.packet.PacketContext; | ||
42 | +import org.onosproject.net.packet.PacketPriority; | ||
43 | +import org.onosproject.net.packet.PacketProcessor; | ||
44 | +import org.onosproject.net.packet.PacketService; | ||
45 | +import org.slf4j.Logger; | ||
46 | + | ||
47 | +/** | ||
48 | + * WORK-IN-PROGRESS: The multicast forwarding application using intent framework. | ||
49 | + */ | ||
50 | +@Component(immediate = true) | ||
51 | +public class McastForwarding { | ||
52 | + | ||
53 | + private final Logger log = getLogger(getClass()); | ||
54 | + private final IpPrefix mcast = IpPrefix.valueOf("224.0.0.0/4"); | ||
55 | + | ||
56 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
57 | + protected PacketService packetService; | ||
58 | + | ||
59 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
60 | + protected CoreService coreService; | ||
61 | + | ||
62 | + private ReactivePacketProcessor processor = new ReactivePacketProcessor(); | ||
63 | + private McastRouteTable mrib; | ||
64 | + private static ApplicationId appId; | ||
65 | + | ||
66 | + /** | ||
67 | + * Active MulticastForwardingIntent. | ||
68 | + */ | ||
69 | + @Activate | ||
70 | + public void activate() { | ||
71 | + appId = coreService.registerApplication("org.onosproject.mfwd"); | ||
72 | + | ||
73 | + packetService.addProcessor(processor, PacketProcessor.director(2)); | ||
74 | + | ||
75 | + // Build a traffic selector for all multicast traffic | ||
76 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
77 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
78 | + selector.matchIPDst(mcast); | ||
79 | + packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId); | ||
80 | + | ||
81 | + mrib = McastRouteTable.getInstance(); | ||
82 | + log.info("Started"); | ||
83 | + } | ||
84 | + | ||
85 | + /** | ||
86 | + * Deactivate Multicast Forwarding Intent. | ||
87 | + */ | ||
88 | + @Deactivate | ||
89 | + public void deactivate() { | ||
90 | + packetService.removeProcessor(processor); | ||
91 | + processor = null; | ||
92 | + log.info("Stopped"); | ||
93 | + } | ||
94 | + | ||
95 | + /** | ||
96 | + * Get the application ID, used by the McastIntentManager. | ||
97 | + * | ||
98 | + * @return the application ID | ||
99 | + */ | ||
100 | + public static ApplicationId getAppId() { | ||
101 | + return appId; | ||
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * Packet processor responsible for forwarding packets along their paths. | ||
106 | + */ | ||
107 | + private class ReactivePacketProcessor implements PacketProcessor { | ||
108 | + | ||
109 | + /** | ||
110 | + * Process incoming packets. | ||
111 | + * | ||
112 | + * @param context packet processing context | ||
113 | + */ | ||
114 | + @Override | ||
115 | + public void process(PacketContext context) { | ||
116 | + // Stop processing if the packet has been handled, since we | ||
117 | + // can't do any more to it. | ||
118 | + if (context.isHandled()) { | ||
119 | + return; | ||
120 | + } | ||
121 | + | ||
122 | + InboundPacket pkt = context.inPacket(); | ||
123 | + Ethernet ethPkt = pkt.parsed(); | ||
124 | + | ||
125 | + if (ethPkt == null) { | ||
126 | + return; | ||
127 | + } | ||
128 | + | ||
129 | + if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4 && | ||
130 | + ethPkt.getEtherType() != Ethernet.TYPE_IPV6) { | ||
131 | + return; | ||
132 | + } | ||
133 | + | ||
134 | + if (ethPkt.getEtherType() == Ethernet.TYPE_IPV6) { | ||
135 | + // Ignore ipv6 at the moment. | ||
136 | + return; | ||
137 | + } | ||
138 | + | ||
139 | + IPv4 ip = (IPv4) ethPkt.getPayload(); | ||
140 | + IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress()); | ||
141 | + IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress()); | ||
142 | + | ||
143 | + log.debug("Packet ({}, {}) has been punted\n" + | ||
144 | + "\tingress port: {}\n", | ||
145 | + saddr.toString(), | ||
146 | + gaddr.toString(), | ||
147 | + context.inPacket().receivedFrom().toString()); | ||
148 | + | ||
149 | + if (!mcast.contains(gaddr)) { | ||
150 | + // Yikes, this is a bad group address | ||
151 | + return; | ||
152 | + } | ||
153 | + | ||
154 | + if (mcast.contains(saddr)) { | ||
155 | + // Yikes, the source address is multicast | ||
156 | + return; | ||
157 | + } | ||
158 | + | ||
159 | + IpPrefix spfx = IpPrefix.valueOf(saddr, 32); | ||
160 | + IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32); | ||
161 | + | ||
162 | + /* | ||
163 | + * Do a best match lookup on the (s, g) of the packet. If an entry does | ||
164 | + * not exist create one and store it's incoming connect point. | ||
165 | + * | ||
166 | + * The connect point is deviceId / portId that the packet entered | ||
167 | + * the SDN network. This differs from traditional mcast where the | ||
168 | + * ingress port would be a specific device. | ||
169 | + */ | ||
170 | + McastRoute entry = mrib.findBestMatch(spfx, gpfx); | ||
171 | + if (entry == null || entry.getSaddr().equals(IPv4.fromIPv4Address(0))) { | ||
172 | + | ||
173 | + /* | ||
174 | + * Create an entry that we can fast drop. | ||
175 | + */ | ||
176 | + entry = mrib.addRoute(spfx, gpfx); | ||
177 | + entry.addIngressPoint(context.inPacket().receivedFrom()); | ||
178 | + } | ||
179 | + | ||
180 | + /* | ||
181 | + * TODO: If we do not have an ingress or any egress connect points we | ||
182 | + * should set up a fast drop entry. | ||
183 | + */ | ||
184 | + if (entry.getIngressPoint() == null) { | ||
185 | + return; | ||
186 | + } | ||
187 | + | ||
188 | + if (entry.getEgressPoints().isEmpty()) { | ||
189 | + return; | ||
190 | + } | ||
191 | + | ||
192 | + /* | ||
193 | + * This is odd, we should not have received a punted packet if an | ||
194 | + * intent was installed unless the intent was not installed | ||
195 | + * correctly. However, we are seeing packets get punted after | ||
196 | + * the intent has been installed. | ||
197 | + * | ||
198 | + * Therefore we are going to forward the packets even if they | ||
199 | + * should have already been forwarded by the intent fabric. | ||
200 | + */ | ||
201 | + if (entry.getIntentKey() != null) { | ||
202 | + return; | ||
203 | + } | ||
204 | + | ||
205 | + entry.setIntent(); | ||
206 | + McastIntentManager im = McastIntentManager.getInstance(); | ||
207 | + im.setIntent(entry); | ||
208 | + | ||
209 | + entry.incrementPuntCount(); | ||
210 | + | ||
211 | + // Send the pack out each of the egress devices & port | ||
212 | + forwardPacketToDst(context, entry); | ||
213 | + } | ||
214 | + } | ||
215 | + | ||
216 | + /** | ||
217 | + * Forward the packet to it's multicast destinations. | ||
218 | + * | ||
219 | + * @param context The packet context | ||
220 | + * @param entry The multicast route entry matching this packet | ||
221 | + */ | ||
222 | + private void forwardPacketToDst(PacketContext context, McastRoute entry) { | ||
223 | + | ||
224 | + // Send the pack out each of the respective egress ports | ||
225 | + for (ConnectPoint egress : entry.getEgressPoints()) { | ||
226 | + TrafficTreatment treatment = DefaultTrafficTreatment.builder() | ||
227 | + .setOutput(egress.port()).build(); | ||
228 | + | ||
229 | + OutboundPacket packet = new DefaultOutboundPacket( | ||
230 | + egress.deviceId(), | ||
231 | + treatment, | ||
232 | + context.inPacket().unparsed()); | ||
233 | + | ||
234 | + packetService.emit(packet); | ||
235 | + } | ||
236 | + } | ||
237 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.impl; | ||
17 | + | ||
18 | +import org.apache.felix.scr.annotations.Activate; | ||
19 | +import org.apache.felix.scr.annotations.Component; | ||
20 | +import org.apache.felix.scr.annotations.Service; | ||
21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
22 | +import org.apache.felix.scr.annotations.Reference; | ||
23 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
24 | +import org.onlab.packet.Ethernet; | ||
25 | +import org.onosproject.net.intent.Intent; | ||
26 | +import org.onosproject.net.intent.SinglePointToMultiPointIntent; | ||
27 | +import org.onosproject.net.intent.IntentService; | ||
28 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
29 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
30 | +import org.onosproject.net.flow.TrafficSelector; | ||
31 | +import org.onosproject.net.flow.TrafficTreatment; | ||
32 | + | ||
33 | +@Component(immediate = true) | ||
34 | +@Service(value = org.onosproject.mfwd.impl.McastIntentManager.class) | ||
35 | +public class McastIntentManager { | ||
36 | + | ||
37 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
38 | + protected IntentService intentService; | ||
39 | + | ||
40 | + private static McastIntentManager instance; | ||
41 | + | ||
42 | + public McastIntentManager() { | ||
43 | + instance = this; | ||
44 | + } | ||
45 | + | ||
46 | + /** | ||
47 | + * Active this component. | ||
48 | + */ | ||
49 | + @Activate | ||
50 | + public void activate() { } | ||
51 | + | ||
52 | + /** | ||
53 | + * Deactivate this component. | ||
54 | + */ | ||
55 | + @Deactivate | ||
56 | + public void deactivate() { | ||
57 | + withdrawAllIntents(); | ||
58 | + } | ||
59 | + | ||
60 | + /** | ||
61 | + * Get instance of this intentManager. | ||
62 | + * | ||
63 | + * @return the instance of this intent manager. | ||
64 | + */ | ||
65 | + public static McastIntentManager getInstance() { | ||
66 | + if (instance == null) { | ||
67 | + instance = new McastIntentManager(); | ||
68 | + } | ||
69 | + return instance; | ||
70 | + } | ||
71 | + | ||
72 | + /** | ||
73 | + * Install the PointToMultipoint forwarding intent. | ||
74 | + * | ||
75 | + * @param mroute multicast route entry | ||
76 | + * @return the intent that has been set or null otherwise | ||
77 | + */ | ||
78 | + public SinglePointToMultiPointIntent setIntent(McastRoute mroute) { | ||
79 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
80 | + TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment(); | ||
81 | + | ||
82 | + if (mroute.getIngressPoint() == null || | ||
83 | + mroute.getEgressPoints().isEmpty()) { | ||
84 | + return null; | ||
85 | + } | ||
86 | + | ||
87 | + /* | ||
88 | + * Match the group AND source addresses. We will also check ether type to | ||
89 | + * determine if we are doing ipv4 or ipv6. | ||
90 | + * | ||
91 | + * If we really wanted to be pendantic we could put in a | ||
92 | + * condition to make sure the ethernet MAC address was also | ||
93 | + * mcast. | ||
94 | + */ | ||
95 | + selector.matchEthType(Ethernet.TYPE_IPV4) | ||
96 | + .matchIPDst(mroute.getGaddr()) | ||
97 | + .matchIPSrc(mroute.getSaddr()); | ||
98 | + | ||
99 | + SinglePointToMultiPointIntent intent = | ||
100 | + SinglePointToMultiPointIntent.builder() | ||
101 | + .appId(McastForwarding.getAppId()) | ||
102 | + .selector(selector.build()) | ||
103 | + .treatment(treatment) | ||
104 | + .ingressPoint(mroute.getIngressPoint()) | ||
105 | + .egressPoints(mroute.getEgressPoints()). | ||
106 | + build(); | ||
107 | + | ||
108 | + intentService.submit(intent); | ||
109 | + return intent; | ||
110 | + } | ||
111 | + | ||
112 | + /** | ||
113 | + * Withdraw the intent represented by this route. | ||
114 | + * | ||
115 | + * @param mroute the mcast route whose intent we want to remove | ||
116 | + */ | ||
117 | + public void withdrawIntent(McastRouteBase mroute) { | ||
118 | + Intent intent = intentService.getIntent(mroute.getIntentKey()); | ||
119 | + intentService.withdraw(intent); | ||
120 | + } | ||
121 | + | ||
122 | + /** | ||
123 | + * Withdraw all intents. | ||
124 | + * | ||
125 | + * This will be called from the deactivate method so we don't leave | ||
126 | + * a mess behind us after we leave. | ||
127 | + */ | ||
128 | + public void withdrawAllIntents() { | ||
129 | + for (Intent intent : intentService.getIntents()) { | ||
130 | + intentService.withdraw(intent); | ||
131 | + } | ||
132 | + } | ||
133 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.impl; | ||
17 | + | ||
18 | +import org.onlab.packet.IpPrefix; | ||
19 | +import org.onosproject.net.ConnectPoint; | ||
20 | +import org.onosproject.net.intent.Key; | ||
21 | +import org.onosproject.net.intent.SinglePointToMultiPointIntent; | ||
22 | + | ||
23 | +import java.util.Set; | ||
24 | + | ||
25 | +/** | ||
26 | + * This McastRouteBase interface is implemented by the McastRouteBase class which | ||
27 | + * in turn acts as the base class for both the McastRouteGroup and McastRouteSource. | ||
28 | + */ | ||
29 | +interface McastRoute { | ||
30 | + | ||
31 | + /** | ||
32 | + * Gets the group addresses. | ||
33 | + * | ||
34 | + * @return group address | ||
35 | + */ | ||
36 | + public IpPrefix getGaddr(); | ||
37 | + | ||
38 | + /** | ||
39 | + * Gets the source address. | ||
40 | + * | ||
41 | + * @return the source address | ||
42 | + */ | ||
43 | + public IpPrefix getSaddr(); | ||
44 | + | ||
45 | + /** | ||
46 | + * Determines if this is an IPv4 multicast route. | ||
47 | + * | ||
48 | + * @return true if it is an IPv4 route | ||
49 | + */ | ||
50 | + public boolean isIp4(); | ||
51 | + | ||
52 | + /** | ||
53 | + * Determines if this is an IPv6 multicast route. | ||
54 | + * | ||
55 | + * @return true if it is an IPv6 route | ||
56 | + */ | ||
57 | + public boolean isIp6(); | ||
58 | + | ||
59 | + /** | ||
60 | + * Add the ingress ConnectPoint with a ConnectPoint. | ||
61 | + * | ||
62 | + * @param ingress ingress point | ||
63 | + */ | ||
64 | + public void addIngressPoint(ConnectPoint ingress); | ||
65 | + | ||
66 | + /** | ||
67 | + * Add the ingress Connect Point using. .. | ||
68 | + * | ||
69 | + * @param deviceId device ID | ||
70 | + * @param portNum port number | ||
71 | + */ | ||
72 | + public void addIngressPoint(String deviceId, long portNum); | ||
73 | + | ||
74 | + /** | ||
75 | + * Get the ingress connect point. | ||
76 | + * | ||
77 | + * @return the ingress connect point | ||
78 | + */ | ||
79 | + public ConnectPoint getIngressPoint(); | ||
80 | + | ||
81 | + /** | ||
82 | + * Add an egress connect point. | ||
83 | + * | ||
84 | + * @param member the egress ConnectPoint to be added | ||
85 | + */ | ||
86 | + public void addEgressPoint(ConnectPoint member); | ||
87 | + | ||
88 | + /** | ||
89 | + * Add an egress connect point. | ||
90 | + * | ||
91 | + * @param deviceId the device ID of the connect point | ||
92 | + * @param portNum the port number of the connect point | ||
93 | + */ | ||
94 | + public void addEgressPoint(String deviceId, long portNum); | ||
95 | + | ||
96 | + /** | ||
97 | + * Get the egress connect points. | ||
98 | + * | ||
99 | + * @return a set of egress connect points | ||
100 | + */ | ||
101 | + public Set<ConnectPoint> getEgressPoints(); | ||
102 | + | ||
103 | + /** | ||
104 | + * Increment the punt count. | ||
105 | + */ | ||
106 | + public void incrementPuntCount(); | ||
107 | + | ||
108 | + /** | ||
109 | + * Get the punt count. | ||
110 | + * | ||
111 | + * @return the punt count | ||
112 | + */ | ||
113 | + public int getPuntCount(); | ||
114 | + | ||
115 | + /** | ||
116 | + * Have the McastIntentManager create an intent, attempt to | ||
117 | + * install the intent and then save the key. | ||
118 | + */ | ||
119 | + public void setIntent(); | ||
120 | + | ||
121 | + /** | ||
122 | + * Set the Intent key. | ||
123 | + * | ||
124 | + * @param intent intent | ||
125 | + */ | ||
126 | + public void setIntent(SinglePointToMultiPointIntent intent); | ||
127 | + | ||
128 | + /** | ||
129 | + * Withdraw the intent if it has been installed. | ||
130 | + */ | ||
131 | + public void withdrawIntent(); | ||
132 | + | ||
133 | + /** | ||
134 | + * Get the intent key. | ||
135 | + * | ||
136 | + * @return the intentKey | ||
137 | + */ | ||
138 | + public Key getIntentKey(); | ||
139 | + | ||
140 | + /** | ||
141 | + * Pretty print the the route. | ||
142 | + * | ||
143 | + * @return a pretty string | ||
144 | + */ | ||
145 | + public String toString(); | ||
146 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.impl; | ||
17 | + | ||
18 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
19 | + | ||
20 | +import org.onlab.packet.IpPrefix; | ||
21 | +import org.onosproject.net.ConnectPoint; | ||
22 | +import org.onosproject.net.DeviceId; | ||
23 | +import org.onosproject.net.PortNumber; | ||
24 | +import org.onosproject.net.intent.SinglePointToMultiPointIntent; | ||
25 | +import org.onosproject.net.intent.Key; | ||
26 | + | ||
27 | +import java.util.Set; | ||
28 | +import java.util.HashSet; | ||
29 | + | ||
30 | +/** | ||
31 | + * McastRouteBase base class for McastRouteGroup and McastRouteSource. | ||
32 | + */ | ||
33 | +public class McastRouteBase implements McastRoute { | ||
34 | + protected final IpPrefix gaddr; | ||
35 | + protected final IpPrefix saddr; | ||
36 | + | ||
37 | + protected ConnectPoint ingressPoint; | ||
38 | + protected Set<ConnectPoint> egressPoints; | ||
39 | + | ||
40 | + protected boolean isGroup = false; | ||
41 | + | ||
42 | + /** | ||
43 | + * How may times has this packet been punted. | ||
44 | + */ | ||
45 | + private int puntCount = 0; | ||
46 | + | ||
47 | + /** | ||
48 | + * If the intentKey is null that means no intent has | ||
49 | + * been installed. | ||
50 | + */ | ||
51 | + protected Key intentKey = null; | ||
52 | + | ||
53 | + /** | ||
54 | + * Create a multicast route. This is the parent class for both the Group | ||
55 | + * and the source. | ||
56 | + * | ||
57 | + * @param saddr source address | ||
58 | + * @param gaddr multicast group address | ||
59 | + */ | ||
60 | + public McastRouteBase(String saddr, String gaddr) { | ||
61 | + this.gaddr = IpPrefix.valueOf(checkNotNull(gaddr)); | ||
62 | + if (saddr == null || saddr.equals("*")) { | ||
63 | + this.saddr = IpPrefix.valueOf(0, 0); | ||
64 | + } else { | ||
65 | + this.saddr = IpPrefix.valueOf(checkNotNull(gaddr)); | ||
66 | + } | ||
67 | + this.init(); | ||
68 | + } | ||
69 | + | ||
70 | + /** | ||
71 | + * Create a multicast group table entry. | ||
72 | + * @param gaddr multicast group address | ||
73 | + */ | ||
74 | + public McastRouteBase(String gaddr) { | ||
75 | + this("*", gaddr); | ||
76 | + } | ||
77 | + | ||
78 | + /** | ||
79 | + * Set the source and group address value of a (*, G) group. | ||
80 | + * | ||
81 | + * @param gpfx the group prefix address | ||
82 | + */ | ||
83 | + public McastRouteBase(IpPrefix gpfx) { | ||
84 | + this(IpPrefix.valueOf(0, 0), gpfx); | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * Create a multicast route constructor. | ||
89 | + * | ||
90 | + * @param saddr source address | ||
91 | + * @param gaddr group address | ||
92 | + */ | ||
93 | + public McastRouteBase(IpPrefix saddr, IpPrefix gaddr) { | ||
94 | + this.saddr = checkNotNull(saddr); | ||
95 | + this.gaddr = checkNotNull(gaddr); | ||
96 | + | ||
97 | + this.init(); | ||
98 | + } | ||
99 | + | ||
100 | + private void init() { | ||
101 | + this.isGroup = (this.saddr.prefixLength() == 0); | ||
102 | + this.ingressPoint = null; | ||
103 | + this.egressPoints = new HashSet(); | ||
104 | + } | ||
105 | + | ||
106 | + /** | ||
107 | + * Get the multicast group address. | ||
108 | + * | ||
109 | + * @return the multicast group address | ||
110 | + */ | ||
111 | + @Override | ||
112 | + public IpPrefix getGaddr() { | ||
113 | + return gaddr; | ||
114 | + } | ||
115 | + | ||
116 | + /** | ||
117 | + * Get the multicast source address. | ||
118 | + * | ||
119 | + * @return the multicast source address | ||
120 | + */ | ||
121 | + @Override | ||
122 | + public IpPrefix getSaddr() { | ||
123 | + return saddr; | ||
124 | + } | ||
125 | + | ||
126 | + /** | ||
127 | + * Is this an IPv4 multicast route. | ||
128 | + * | ||
129 | + * @return true if it is an IPv4 route | ||
130 | + */ | ||
131 | + @Override | ||
132 | + public boolean isIp4() { | ||
133 | + return gaddr.isIp4(); | ||
134 | + } | ||
135 | + | ||
136 | + /** | ||
137 | + * Is this an IPv6 multicast route. | ||
138 | + * | ||
139 | + * @return true if it is an IPv6 route | ||
140 | + */ | ||
141 | + @Override | ||
142 | + public boolean isIp6() { | ||
143 | + return gaddr.isIp6(); | ||
144 | + } | ||
145 | + | ||
146 | + /** | ||
147 | + * Is this a multicast group route? | ||
148 | + * | ||
149 | + * @return true if it is a multicast group route. | ||
150 | + */ | ||
151 | + public boolean isGroup() { | ||
152 | + return isGroup; | ||
153 | + } | ||
154 | + | ||
155 | + /** | ||
156 | + * @return true if this is (S, G) false if it (*, G). | ||
157 | + */ | ||
158 | + public boolean isSource() { | ||
159 | + return (!isGroup); | ||
160 | + } | ||
161 | + | ||
162 | + /** | ||
163 | + * Add an ingress point to this route. | ||
164 | + * | ||
165 | + * @param ingress incoming connect point | ||
166 | + */ | ||
167 | + @Override | ||
168 | + public void addIngressPoint(ConnectPoint ingress) { | ||
169 | + ingressPoint = checkNotNull(ingress); | ||
170 | + } | ||
171 | + | ||
172 | + /** | ||
173 | + * Add or modify the ingress connect point. | ||
174 | + * | ||
175 | + * @param deviceId the switch device Id | ||
176 | + * @param portNum the ingress port number | ||
177 | + */ | ||
178 | + @Override | ||
179 | + public void addIngressPoint(String deviceId, long portNum) { | ||
180 | + ingressPoint = new ConnectPoint( | ||
181 | + DeviceId.deviceId(deviceId), | ||
182 | + PortNumber.portNumber(portNum)); | ||
183 | + } | ||
184 | + | ||
185 | + /** | ||
186 | + * Get the ingress ConnectPoint. | ||
187 | + * | ||
188 | + * @return the ingress ConnectPoint | ||
189 | + */ | ||
190 | + @Override | ||
191 | + public ConnectPoint getIngressPoint() { | ||
192 | + return this.ingressPoint; | ||
193 | + } | ||
194 | + | ||
195 | + /** | ||
196 | + * Add an egress ConnectPoint. | ||
197 | + * | ||
198 | + * @param member member egress connect point | ||
199 | + */ | ||
200 | + @Override | ||
201 | + public void addEgressPoint(ConnectPoint member) { | ||
202 | + egressPoints.add(checkNotNull(member)); | ||
203 | + } | ||
204 | + | ||
205 | + /** | ||
206 | + * Add an egress ConnectPoint. | ||
207 | + * | ||
208 | + * @param deviceId deviceId of the connect point | ||
209 | + * @param portNum portNum of the connect point | ||
210 | + */ | ||
211 | + @Override | ||
212 | + public void addEgressPoint(String deviceId, long portNum) { | ||
213 | + ConnectPoint cp = new ConnectPoint(DeviceId.deviceId(deviceId), PortNumber.portNumber(portNum)); | ||
214 | + this.egressPoints.add(cp); | ||
215 | + } | ||
216 | + | ||
217 | + /** | ||
218 | + * Get egress connect points for the route. | ||
219 | + * | ||
220 | + * @return Set of egress connect points | ||
221 | + */ | ||
222 | + @Override | ||
223 | + public Set<ConnectPoint> getEgressPoints() { | ||
224 | + return egressPoints; | ||
225 | + } | ||
226 | + | ||
227 | + /** | ||
228 | + * Get the number of times the packet has been punted. | ||
229 | + * | ||
230 | + * @return the punt count | ||
231 | + */ | ||
232 | + @Override | ||
233 | + public int getPuntCount() { | ||
234 | + return puntCount; | ||
235 | + } | ||
236 | + | ||
237 | + /** | ||
238 | + * Increment the punt count. | ||
239 | + * | ||
240 | + * TODO: we need to handle wrapping. | ||
241 | + */ | ||
242 | + @Override | ||
243 | + public void incrementPuntCount() { | ||
244 | + puntCount++; | ||
245 | + } | ||
246 | + | ||
247 | + /** | ||
248 | + * Have the McastIntentManager create and set the intent, then save the intent key. | ||
249 | + * | ||
250 | + * If we already have an intent, we will first withdraw the existing intent and | ||
251 | + * replace it with a new one. This will support the case where the ingress connectPoint | ||
252 | + * or group of egress connectPoints change. | ||
253 | + */ | ||
254 | + @Override | ||
255 | + public void setIntent() { | ||
256 | + if (this.intentKey != null) { | ||
257 | + this.withdrawIntent(); | ||
258 | + } | ||
259 | + McastIntentManager im = McastIntentManager.getInstance(); | ||
260 | + SinglePointToMultiPointIntent intent = im.setIntent(this); | ||
261 | + this.intentKey = intent.key(); | ||
262 | + } | ||
263 | + | ||
264 | + /** | ||
265 | + * Set the Intent key. | ||
266 | + * | ||
267 | + * @param intent intent | ||
268 | + */ | ||
269 | + @Override | ||
270 | + public void setIntent(SinglePointToMultiPointIntent intent) { | ||
271 | + intentKey = intent.key(); | ||
272 | + } | ||
273 | + | ||
274 | + /** | ||
275 | + * Get the intent key represented by this route. | ||
276 | + * | ||
277 | + * @return intentKey | ||
278 | + */ | ||
279 | + @Override | ||
280 | + public Key getIntentKey() { | ||
281 | + return this.intentKey; | ||
282 | + } | ||
283 | + | ||
284 | + | ||
285 | + /** | ||
286 | + * Withdraw the intent and set the key to null. | ||
287 | + */ | ||
288 | + @Override | ||
289 | + public void withdrawIntent() { | ||
290 | + if (intentKey == null) { | ||
291 | + // nothing to withdraw | ||
292 | + return; | ||
293 | + } | ||
294 | + McastIntentManager im = McastIntentManager.getInstance(); | ||
295 | + im.withdrawIntent(this); | ||
296 | + this.intentKey = null; | ||
297 | + } | ||
298 | + | ||
299 | + /** | ||
300 | + * Pretty Print this Multicast Route. Works for McastRouteSource and McastRouteGroup. | ||
301 | + * | ||
302 | + * @return pretty string of the multicast route | ||
303 | + */ | ||
304 | + @Override | ||
305 | + public String toString() { | ||
306 | + String out = String.format("(%s, %s)\n\t", | ||
307 | + saddr.toString(), gaddr.toString()); | ||
308 | + | ||
309 | + out += "intent: "; | ||
310 | + out += (intentKey == null) ? "not installed" : this.intentKey.toString(); | ||
311 | + out += "\n\tingress: "; | ||
312 | + out += (ingressPoint == null) ? "NULL" : ingressPoint.toString(); | ||
313 | + out += "\n\tegress: {\n"; | ||
314 | + if (egressPoints != null && !egressPoints.isEmpty()) { | ||
315 | + for (ConnectPoint eg : egressPoints) { | ||
316 | + out += "\t\t" + eg.toString() + "\n"; | ||
317 | + } | ||
318 | + } | ||
319 | + out += ("\t}\n"); | ||
320 | + out += ("\tpunted: " + this.getPuntCount() + "\n"); | ||
321 | + return out; | ||
322 | + } | ||
323 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.impl; | ||
17 | + | ||
18 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
19 | +import java.util.HashMap; | ||
20 | +import org.onlab.packet.IpPrefix; | ||
21 | + | ||
22 | +/** | ||
23 | + * The McastRouteGroup extends the McastRouteBase class and serves two purposes: | ||
24 | + * first it represents a (*, G) multicast route entry. Second it serves | ||
25 | + * as a container for all (S, G) multicast route entries that belong | ||
26 | + * to the same group address. | ||
27 | + */ | ||
28 | +public class McastRouteGroup extends McastRouteBase { | ||
29 | + private HashMap<IpPrefix, McastRouteSource> sources; | ||
30 | + | ||
31 | + /** | ||
32 | + * Class constructor. | ||
33 | + * | ||
34 | + * @param gaddr - String representation of group address. | ||
35 | + */ | ||
36 | + public McastRouteGroup(String gaddr) { | ||
37 | + super(checkNotNull(gaddr)); | ||
38 | + this.init(); | ||
39 | + } | ||
40 | + | ||
41 | + /** | ||
42 | + * Create a multicast group. | ||
43 | + * | ||
44 | + * @param gpfx - Group address | ||
45 | + */ | ||
46 | + public McastRouteGroup(IpPrefix gpfx) { | ||
47 | + super(checkNotNull(gpfx)); | ||
48 | + this.init(); | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * Common initialization used by constructors. | ||
53 | + */ | ||
54 | + private void init() { | ||
55 | + this.sources = new HashMap(); | ||
56 | + super.isGroup = true; | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * Find a specific multicast source address for this group. | ||
61 | + * | ||
62 | + * @param saddr the source address | ||
63 | + * @return the multicast source route or null if it does not exist | ||
64 | + */ | ||
65 | + public McastRouteSource findSource(IpPrefix saddr) { | ||
66 | + return this.sources.get(checkNotNull(saddr)); | ||
67 | + } | ||
68 | + | ||
69 | + /** | ||
70 | + * Return the entire set of multicast sources for this group. | ||
71 | + * | ||
72 | + * @return the set of multicast sources | ||
73 | + */ | ||
74 | + public HashMap<IpPrefix, McastRouteSource> getSources() { | ||
75 | + return this.sources; | ||
76 | + } | ||
77 | + | ||
78 | + /** | ||
79 | + * Add a new McastRouteSource to this group. | ||
80 | + * | ||
81 | + * @param src the multicast source | ||
82 | + */ | ||
83 | + public void addSource(McastRouteSource src) { | ||
84 | + checkNotNull(src); | ||
85 | + this.sources.put(src.getSaddr(), src); | ||
86 | + } | ||
87 | + | ||
88 | + /** | ||
89 | + * Remove the source with this specific IpPrefix from this group entry. | ||
90 | + * | ||
91 | + * @param spfx IP Prefix of the source to be removed | ||
92 | + * @return the source route that was just removed | ||
93 | + */ | ||
94 | + public McastRouteSource removeSource(IpPrefix spfx) { | ||
95 | + McastRouteSource src = this.sources.remove(spfx); | ||
96 | + src.withdrawIntent(); | ||
97 | + return src; | ||
98 | + } | ||
99 | + | ||
100 | + /** | ||
101 | + * Remove all sources from this. | ||
102 | + */ | ||
103 | + public void removeSources() { | ||
104 | + for (McastRouteSource src : this.sources.values()) { | ||
105 | + src.withdrawIntent(); | ||
106 | + this.sources.remove(src.getSaddr()); | ||
107 | + } | ||
108 | + } | ||
109 | + | ||
110 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.impl; | ||
17 | + | ||
18 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
19 | +import org.onlab.packet.IpPrefix; | ||
20 | + | ||
21 | +/** | ||
22 | + * This class represents and specific multicast senders source address. Objects from | ||
23 | + * this class will belong to the sources collection of the multicast group. | ||
24 | + */ | ||
25 | +public class McastRouteSource extends McastRouteBase { | ||
26 | + | ||
27 | + // A reference to our parent group | ||
28 | + private McastRouteGroup group; | ||
29 | + | ||
30 | + /** | ||
31 | + * Create a multicast source with IpPrefixes. | ||
32 | + * | ||
33 | + * @param source the source address | ||
34 | + * @param group the group address | ||
35 | + */ | ||
36 | + public McastRouteSource(IpPrefix source, IpPrefix group) { | ||
37 | + super(checkNotNull(source), checkNotNull(group)); | ||
38 | + } | ||
39 | + | ||
40 | + /** | ||
41 | + * Set our parent multicast group. | ||
42 | + * | ||
43 | + * @param group the group this source belongs to | ||
44 | + */ | ||
45 | + public void setGroup(McastRouteGroup group) { | ||
46 | + this.group = group; | ||
47 | + } | ||
48 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
This diff is collapsed. Click to expand it.
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.mfwd.rest; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
20 | + | ||
21 | +import java.io.IOException; | ||
22 | +import java.io.InputStream; | ||
23 | +import java.util.Map; | ||
24 | + | ||
25 | +import javax.ws.rs.Consumes; | ||
26 | +import javax.ws.rs.GET; | ||
27 | +import javax.ws.rs.POST; | ||
28 | +import javax.ws.rs.Path; | ||
29 | +import javax.ws.rs.Produces; | ||
30 | +import javax.ws.rs.core.MediaType; | ||
31 | +import javax.ws.rs.core.Response; | ||
32 | + | ||
33 | +import org.onlab.packet.IpPrefix; | ||
34 | +import org.onlab.rest.BaseResource; | ||
35 | +import org.onosproject.mfwd.impl.McastRouteGroup; | ||
36 | +import org.onosproject.mfwd.impl.McastRouteTable; | ||
37 | + | ||
38 | +/** | ||
39 | + * Rest API for Multicast Forwarding. | ||
40 | + */ | ||
41 | +@Path("mcast") | ||
42 | +public class McastResource extends BaseResource { | ||
43 | + | ||
44 | + /** | ||
45 | + * Retrieve the multicast route table. | ||
46 | + * @return the multicast route table. | ||
47 | + * @throws IOException if an error occurs | ||
48 | + */ | ||
49 | + @GET | ||
50 | + @Produces(MediaType.APPLICATION_JSON) | ||
51 | + public Response showAll() throws IOException { | ||
52 | + ObjectMapper mapper = new ObjectMapper(); | ||
53 | + McastRouteTable mcastRouteTable = McastRouteTable.getInstance(); | ||
54 | + Map<IpPrefix, McastRouteGroup> map = mcastRouteTable.getMrib4(); | ||
55 | + return Response.ok(mapper.createObjectNode().toString()).build(); | ||
56 | + } | ||
57 | + | ||
58 | + /** | ||
59 | + * Static join of a multicast flow. | ||
60 | + * @param input source, group, ingress connectPoint egress connectPoints | ||
61 | + * @return status of static join | ||
62 | + * @throws IOException if an error occurs | ||
63 | + */ | ||
64 | + @POST | ||
65 | + @Consumes(MediaType.APPLICATION_JSON) | ||
66 | + @Produces(MediaType.APPLICATION_JSON) | ||
67 | + public Response join(InputStream input) throws IOException { | ||
68 | + ObjectMapper mapper = new ObjectMapper(); | ||
69 | + JsonNode cfg = mapper.readTree(input); | ||
70 | + return null; | ||
71 | + } | ||
72 | +} |
1 | +<!-- | ||
2 | + ~ Copyright 2014 Open Networking Laboratory | ||
3 | + ~ | ||
4 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + ~ you may not use this file except in compliance with the License. | ||
6 | + ~ You may obtain a copy of the License at | ||
7 | + ~ | ||
8 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + ~ | ||
10 | + ~ Unless required by applicable law or agreed to in writing, software | ||
11 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + ~ See the License for the specific language governing permissions and | ||
14 | + ~ limitations under the License. | ||
15 | + --> | ||
16 | +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> | ||
17 | + | ||
18 | + <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> | ||
19 | + <command> | ||
20 | + <action class="org.onosproject.mfwd.cli.McastJoinCommand"/> | ||
21 | + </command> | ||
22 | + <command> | ||
23 | + <action class="org.onosproject.mfwd.cli.McastDeleteCommand"/> | ||
24 | + </command> | ||
25 | + <command> | ||
26 | + <action class="org.onosproject.mfwd.cli.McastShowCommand"/> | ||
27 | + </command> | ||
28 | + </command-bundle> | ||
29 | + | ||
30 | +</blueprint> |
apps/mfwd/src/main/webapp/WEB-INF/web.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | +~ Copyright 2014 Open Networking Laboratory | ||
4 | +~ | ||
5 | +~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | +~ you may not use this file except in compliance with the License. | ||
7 | +~ You may obtain a copy of the License at | ||
8 | +~ | ||
9 | +~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | +~ | ||
11 | +~ Unless required by applicable law or agreed to in writing, software | ||
12 | +~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | +~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | +~ See the License for the specific language governing permissions and | ||
15 | +~ limitations under the License. | ||
16 | +--> | ||
17 | +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" | ||
18 | + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" | ||
19 | + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" | ||
20 | + id="ONOS" version="2.5"> | ||
21 | + <display-name>ONOS APP MFWD</display-name> | ||
22 | + | ||
23 | + <servlet> | ||
24 | + <servlet-name>JAX-RS Service</servlet-name> | ||
25 | + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> | ||
26 | + <init-param> | ||
27 | + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name> | ||
28 | + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value> | ||
29 | + </init-param> | ||
30 | + <init-param> | ||
31 | + <param-name>com.sun.jersey.config.property.classnames</param-name> | ||
32 | + <param-value> | ||
33 | + org.onosproject.mfwd.rest.McastResource | ||
34 | + </param-value> | ||
35 | + </init-param> | ||
36 | + <load-on-startup>1</load-on-startup> | ||
37 | + </servlet> | ||
38 | + | ||
39 | + <servlet-mapping> | ||
40 | + <servlet-name>JAX-RS Service</servlet-name> | ||
41 | + <url-pattern>/*</url-pattern> | ||
42 | + </servlet-mapping> | ||
43 | + | ||
44 | +</web-app> |
apps/pim/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2015 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
18 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
20 | + <modelVersion>4.0.0</modelVersion> | ||
21 | + | ||
22 | + <parent> | ||
23 | + <groupId>org.onosproject</groupId> | ||
24 | + <artifactId>onos-apps</artifactId> | ||
25 | + <version>1.4.0-SNAPSHOT</version> | ||
26 | + <relativePath>../pom.xml</relativePath> | ||
27 | + </parent> | ||
28 | + | ||
29 | + <artifactId>onos-app-pim</artifactId> | ||
30 | + <packaging>bundle</packaging> | ||
31 | + | ||
32 | + <description>Protocol Independent Multicast Emulation</description> | ||
33 | + | ||
34 | + <properties> | ||
35 | + <onos.app.name>org.onosproject.pim</onos.app.name> | ||
36 | + </properties> | ||
37 | + | ||
38 | + <dependencies> | ||
39 | + <dependency> | ||
40 | + <groupId>org.onosproject</groupId> | ||
41 | + <artifactId>onos-api</artifactId> | ||
42 | + <version>${project.version}</version> | ||
43 | + </dependency> | ||
44 | + | ||
45 | + <dependency> | ||
46 | + <groupId>org.onosproject</groupId> | ||
47 | + <artifactId>onos-cli</artifactId> | ||
48 | + <version>${project.version}</version> | ||
49 | + </dependency> | ||
50 | + | ||
51 | + | ||
52 | + <dependency> | ||
53 | + <groupId>org.onosproject</groupId> | ||
54 | + <artifactId>onlab-osgi</artifactId> | ||
55 | + <version>${project.version}</version> | ||
56 | + </dependency> | ||
57 | + | ||
58 | + <dependency> | ||
59 | + <groupId>org.onosproject</groupId> | ||
60 | + <artifactId>onlab-junit</artifactId> | ||
61 | + <scope>test</scope> | ||
62 | + </dependency> | ||
63 | + | ||
64 | + <!-- This is needed by ComponentContext, used for tunable configuration --> | ||
65 | + <dependency> | ||
66 | + <groupId>org.osgi</groupId> | ||
67 | + <artifactId>org.osgi.compendium</artifactId> | ||
68 | + </dependency> | ||
69 | + | ||
70 | + <dependency> | ||
71 | + <groupId>org.apache.karaf.shell</groupId> | ||
72 | + <artifactId>org.apache.karaf.shell.console</artifactId> | ||
73 | + </dependency> | ||
74 | + | ||
75 | + <dependency> | ||
76 | + <groupId>org.apache.felix</groupId> | ||
77 | + <artifactId>org.apache.felix.scr.annotations</artifactId> | ||
78 | + <version>1.9.8</version> | ||
79 | + <scope>provided</scope> | ||
80 | + </dependency> | ||
81 | + </dependencies> | ||
82 | + | ||
83 | + <build> | ||
84 | + <plugins> | ||
85 | + <plugin> | ||
86 | + <groupId>org.apache.felix</groupId> | ||
87 | + <artifactId>maven-bundle-plugin</artifactId> | ||
88 | + <extensions>true</extensions> | ||
89 | + <configuration> | ||
90 | + <instructions> | ||
91 | + <Bundle-SymbolicName> | ||
92 | + ${project.groupId}.${project.artifactId} | ||
93 | + </Bundle-SymbolicName> | ||
94 | + <Import-Package> | ||
95 | + org.slf4j, | ||
96 | + org.osgi.framework, | ||
97 | + org.apache.commons.lang.math.*, | ||
98 | + com.google.common.*, | ||
99 | + org.onlab.packet.*, | ||
100 | + org.onlab.rest.*, | ||
101 | + org.onosproject.*, | ||
102 | + org.onosproject.mfwd.impl.*; | ||
103 | + org.onlab.util.*, | ||
104 | + org.jboss.netty.util.* | ||
105 | + </Import-Package> | ||
106 | + </instructions> | ||
107 | + </configuration> | ||
108 | + </plugin> | ||
109 | + <plugin> | ||
110 | + <groupId>org.apache.maven.plugins</groupId> | ||
111 | + <artifactId>maven-compiler-plugin</artifactId> | ||
112 | + <version>2.5.1</version> | ||
113 | + <configuration> | ||
114 | + <source>1.8</source> | ||
115 | + <target>1.8</target> | ||
116 | + </configuration> | ||
117 | + </plugin> | ||
118 | + </plugins> | ||
119 | + </build> | ||
120 | +</project> |
1 | +/* | ||
2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pim.cli; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | +import org.onosproject.net.ConnectPoint; | ||
22 | +import org.onosproject.pim.impl.PIMNeighbors; | ||
23 | +import org.onosproject.pim.impl.PIMNeighborsCodec; | ||
24 | + | ||
25 | +import java.util.HashMap; | ||
26 | + | ||
27 | +@Command(scope = "onos", name = "pim-show", description = "Displays the pim neighbors") | ||
28 | +public class PIMShowCommand extends AbstractShellCommand { | ||
29 | + | ||
30 | + // prints either the json or cli version of the hash map connect point | ||
31 | + // neighbors from the PIMNeighbors class. | ||
32 | + @Override | ||
33 | + protected void execute() { | ||
34 | + // grab connect point neighbors hash map to send in to json encoder. | ||
35 | + HashMap<ConnectPoint, PIMNeighbors> pimNbrs = PIMNeighbors.getConnectPointNeighbors(); | ||
36 | + if (outputJson()) { | ||
37 | + print("%s", json(pimNbrs)); | ||
38 | + } else { | ||
39 | + print(PIMNeighbors.printPimNeighbors()); | ||
40 | + } | ||
41 | + } | ||
42 | + | ||
43 | + private JsonNode json(HashMap<ConnectPoint, PIMNeighbors> pimNbrs) { | ||
44 | + return new PIMNeighborsCodec().encode(pimNbrs, this); | ||
45 | + } | ||
46 | + | ||
47 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pim.impl; | ||
17 | + | ||
18 | +import static org.slf4j.LoggerFactory.getLogger; | ||
19 | + | ||
20 | +import org.apache.felix.scr.annotations.Activate; | ||
21 | +import org.apache.felix.scr.annotations.Component; | ||
22 | +import org.apache.felix.scr.annotations.Deactivate; | ||
23 | +import org.apache.felix.scr.annotations.Reference; | ||
24 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
25 | +import org.onlab.packet.Ethernet; | ||
26 | +import org.onlab.packet.IPv4; | ||
27 | +import org.onlab.packet.Ip4Address; | ||
28 | +import org.onlab.packet.IpAddress; | ||
29 | +import org.onlab.packet.IpPrefix; | ||
30 | +import org.onlab.packet.PIM; | ||
31 | +import org.onosproject.core.ApplicationId; | ||
32 | +import org.onosproject.core.CoreService; | ||
33 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
34 | +import org.onosproject.net.flow.TrafficSelector; | ||
35 | +import org.onosproject.net.packet.InboundPacket; | ||
36 | +import org.onosproject.net.packet.PacketContext; | ||
37 | +import org.onosproject.net.packet.PacketPriority; | ||
38 | +import org.onosproject.net.packet.PacketProcessor; | ||
39 | +import org.onosproject.net.packet.PacketService; | ||
40 | +import org.slf4j.Logger; | ||
41 | + | ||
42 | +/** | ||
43 | + * Protocol Independent Multicast Emulation. | ||
44 | + */ | ||
45 | +@Component(immediate = true) | ||
46 | +public class PIMComponent { | ||
47 | + private final Logger log = getLogger(getClass()); | ||
48 | + | ||
49 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
50 | + protected PacketService packetService; | ||
51 | + | ||
52 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
53 | + protected CoreService coreService; | ||
54 | + | ||
55 | + private PIMPacketProcessor processor = new PIMPacketProcessor(); | ||
56 | + private static ApplicationId appId; | ||
57 | + | ||
58 | + @Activate | ||
59 | + public void activate() { | ||
60 | + appId = coreService.registerApplication("org.onosproject.pim"); | ||
61 | + | ||
62 | + packetService.addProcessor(processor, PacketProcessor.director(1)); | ||
63 | + | ||
64 | + // Build a traffic selector for all multicast traffic | ||
65 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
66 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
67 | + selector.matchIPProtocol(IPv4.PROTOCOL_PIM); | ||
68 | + packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId); | ||
69 | + | ||
70 | + log.info("Started"); | ||
71 | + } | ||
72 | + | ||
73 | + @Deactivate | ||
74 | + public void deactivate() { | ||
75 | + packetService.removeProcessor(processor); | ||
76 | + processor = null; | ||
77 | + log.info("Stopped"); | ||
78 | + } | ||
79 | + | ||
80 | + /** | ||
81 | + * Packet processor responsible for handling IGMP packets. | ||
82 | + */ | ||
83 | + private class PIMPacketProcessor implements PacketProcessor { | ||
84 | + | ||
85 | + @Override | ||
86 | + public void process(PacketContext context) { | ||
87 | + // Stop processing if the packet has been handled, since we | ||
88 | + // can't do any more to it. | ||
89 | + if (context.isHandled()) { | ||
90 | + return; | ||
91 | + } | ||
92 | + | ||
93 | + InboundPacket pkt = context.inPacket(); | ||
94 | + if (pkt == null) { | ||
95 | + return; | ||
96 | + } | ||
97 | + | ||
98 | + Ethernet ethPkt = pkt.parsed(); | ||
99 | + if (ethPkt == null) { | ||
100 | + return; | ||
101 | + } | ||
102 | + | ||
103 | + /* | ||
104 | + * IPv6 MLD packets are handled by ICMP6. We'll only deal | ||
105 | + * with IPv4. | ||
106 | + */ | ||
107 | + if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) { | ||
108 | + return; | ||
109 | + } | ||
110 | + | ||
111 | + IPv4 ip = (IPv4) ethPkt.getPayload(); | ||
112 | + IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress()); | ||
113 | + IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress()); | ||
114 | + log.debug("Packet (" + saddr.toString() + ", " + gaddr.toString() + | ||
115 | + "\tingress port: " + context.inPacket().receivedFrom().toString()); | ||
116 | + | ||
117 | + if (ip.getProtocol() != IPv4.PROTOCOL_PIM) { | ||
118 | + log.debug("PIM Picked up a non PIM packet: IP protocol: " + ip.getProtocol()); | ||
119 | + return; | ||
120 | + } | ||
121 | + | ||
122 | + // TODO: check incoming to be PIM.PIM_ADDRESS or "Our" address. | ||
123 | + IpPrefix spfx = IpPrefix.valueOf(saddr, 32); | ||
124 | + IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32); | ||
125 | + | ||
126 | + PIM pim = (PIM) ip.getPayload(); | ||
127 | + switch (pim.getPimMsgType()) { | ||
128 | + | ||
129 | + case PIM.TYPE_HELLO: | ||
130 | + PIMNeighbors.processHello(ethPkt, context.inPacket().receivedFrom()); | ||
131 | + break; | ||
132 | + | ||
133 | + case PIM.TYPE_JOIN_PRUNE_REQUEST: | ||
134 | + // Create the function | ||
135 | + break; | ||
136 | + | ||
137 | + case PIM.TYPE_ASSERT: | ||
138 | + case PIM.TYPE_BOOTSTRAP: | ||
139 | + case PIM.TYPE_CANDIDATE_RP_ADV: | ||
140 | + case PIM.TYPE_GRAFT: | ||
141 | + case PIM.TYPE_GRAFT_ACK: | ||
142 | + case PIM.TYPE_REGISTER: | ||
143 | + case PIM.TYPE_REGISTER_STOP: | ||
144 | + log.debug("Unsupported PIM message type: " + pim.getPimMsgType()); | ||
145 | + break; | ||
146 | + | ||
147 | + default: | ||
148 | + log.debug("Unkown PIM message type: " + pim.getPimMsgType()); | ||
149 | + break; | ||
150 | + } | ||
151 | + } | ||
152 | + } | ||
153 | +} |
1 | +/* | ||
2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in reliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pim.impl; | ||
17 | + | ||
18 | +import org.jboss.netty.util.Timeout; | ||
19 | +import org.jboss.netty.util.TimerTask; | ||
20 | +import org.onlab.packet.IpAddress; | ||
21 | +import org.onlab.packet.MacAddress; | ||
22 | +import org.onlab.packet.pim.PIMHello; | ||
23 | +import org.onlab.packet.pim.PIMHelloOption; | ||
24 | +import org.onosproject.net.ConnectPoint; | ||
25 | +import org.slf4j.Logger; | ||
26 | + | ||
27 | +import java.nio.ByteBuffer; | ||
28 | +import java.util.concurrent.TimeUnit; | ||
29 | + | ||
30 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
31 | +import static org.slf4j.LoggerFactory.getLogger; | ||
32 | + | ||
33 | +/** | ||
34 | + * PIMNeighbor represents all the PIM routers that have sent us | ||
35 | + * hello messages, or that possibly have been statically configured. | ||
36 | + */ | ||
37 | +public class PIMNeighbor { | ||
38 | + private final Logger log = getLogger(getClass()); | ||
39 | + | ||
40 | + // The primary address of this PIM neighbor | ||
41 | + private IpAddress primaryAddr; | ||
42 | + | ||
43 | + // The MacAddress of this neighbor | ||
44 | + private MacAddress macAddress; | ||
45 | + | ||
46 | + // The ConnectPoint this PIM neighbor is connected to. | ||
47 | + private ConnectPoint connectPoint; | ||
48 | + | ||
49 | + // Is this neighbor us? | ||
50 | + private boolean isThisUs = false; | ||
51 | + | ||
52 | + // The option values this neighbor has sent us. | ||
53 | + private int priority = 0; | ||
54 | + private int genId = 0; | ||
55 | + private short holdtime = 0; | ||
56 | + | ||
57 | + // Is this pim neighbor the DR? | ||
58 | + private boolean isDr = false; | ||
59 | + | ||
60 | + // Timeout for this neighbor | ||
61 | + private volatile Timeout timeout; | ||
62 | + | ||
63 | + private boolean reelect = false; | ||
64 | + | ||
65 | + // A back pointer the neighbors list this neighbor belongs to. | ||
66 | + private PIMNeighbors neighbors; | ||
67 | + | ||
68 | + /** | ||
69 | + * Construct this neighbor from the address and connect point. | ||
70 | + * | ||
71 | + * @param ipaddr IP Address of neighbor | ||
72 | + * @param macaddr MAC Address of the neighbor | ||
73 | + * @param cp The ConnectPoint of this neighbor | ||
74 | + */ | ||
75 | + public PIMNeighbor(IpAddress ipaddr, MacAddress macaddr, ConnectPoint cp) { | ||
76 | + this.macAddress = macaddr; | ||
77 | + this.primaryAddr = ipaddr; | ||
78 | + this.connectPoint = cp; | ||
79 | + this.resetTimeout(); | ||
80 | + } | ||
81 | + | ||
82 | + /** | ||
83 | + * Get the primary address of this neighbor. | ||
84 | + * | ||
85 | + * @return the primary IP address. | ||
86 | + */ | ||
87 | + public IpAddress getPrimaryAddr() { | ||
88 | + return primaryAddr; | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * Set the primary address of this neighbor. | ||
93 | + * | ||
94 | + * @param primaryAddr the address we'll use when sending hello messages | ||
95 | + */ | ||
96 | + public void setPrimaryAddr(IpAddress primaryAddr) { | ||
97 | + this.primaryAddr = primaryAddr; | ||
98 | + } | ||
99 | + | ||
100 | + /** | ||
101 | + * Get the priority this neighbor has advertised to us. | ||
102 | + * | ||
103 | + * @return the priority | ||
104 | + */ | ||
105 | + public int getPriority() { | ||
106 | + return priority; | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * Set the priority for this neighbor. | ||
111 | + * | ||
112 | + * @param priority This neighbors priority. | ||
113 | + */ | ||
114 | + public void setPriority(int priority) { | ||
115 | + this.priority = priority; | ||
116 | + } | ||
117 | + | ||
118 | + /** | ||
119 | + * Get the generation ID. | ||
120 | + * | ||
121 | + * @return the generation ID. | ||
122 | + */ | ||
123 | + public int getGenId() { | ||
124 | + return genId; | ||
125 | + } | ||
126 | + | ||
127 | + /** | ||
128 | + * Set the generation ID. | ||
129 | + * | ||
130 | + * @param genId the generation ID. | ||
131 | + */ | ||
132 | + public void setGenId(int genId) { | ||
133 | + this.genId = genId; | ||
134 | + } | ||
135 | + | ||
136 | + /** | ||
137 | + * Get the holdtime for this neighbor. | ||
138 | + * | ||
139 | + * @return the holdtime | ||
140 | + */ | ||
141 | + public short getHoldtime() { | ||
142 | + return holdtime; | ||
143 | + } | ||
144 | + | ||
145 | + /** | ||
146 | + * Set the holdtime for this neighbor. | ||
147 | + * | ||
148 | + * @param holdtime the holdtime. | ||
149 | + */ | ||
150 | + public void setholdtime(short holdtime) { | ||
151 | + this.holdtime = holdtime; | ||
152 | + } | ||
153 | + | ||
154 | + /** | ||
155 | + * Is this neighbor the designated router on this connect point? | ||
156 | + * | ||
157 | + * @return true if so, false if not. | ||
158 | + */ | ||
159 | + public boolean isDr() { | ||
160 | + return isDr; | ||
161 | + } | ||
162 | + | ||
163 | + /** | ||
164 | + * Set this router as the designated router on this connect point. | ||
165 | + * | ||
166 | + * @param isDr True is this neighbor is the DR false otherwise | ||
167 | + */ | ||
168 | + public void setIsDr(boolean isDr) { | ||
169 | + this.isDr = isDr; | ||
170 | + } | ||
171 | + | ||
172 | + /** | ||
173 | + * The ConnectPoint this neighbor is connected to. | ||
174 | + * | ||
175 | + * @return the ConnectPoint | ||
176 | + */ | ||
177 | + public ConnectPoint getConnectPoint() { | ||
178 | + return connectPoint; | ||
179 | + } | ||
180 | + | ||
181 | + /** | ||
182 | + * Set the ConnectPoint this router is connected to. | ||
183 | + * | ||
184 | + * @param connectPoint the ConnectPoint this router is connected to. | ||
185 | + */ | ||
186 | + public void setConnectPoint(ConnectPoint connectPoint) { | ||
187 | + this.connectPoint = connectPoint; | ||
188 | + } | ||
189 | + | ||
190 | + /** | ||
191 | + * Set a back pointer to the neighbors list this neighbor is a member of. | ||
192 | + * | ||
193 | + * @param neighbors the neighbor list this neighbor belongs to | ||
194 | + */ | ||
195 | + public void setNeighbors(PIMNeighbors neighbors) { | ||
196 | + this.neighbors = neighbors; | ||
197 | + } | ||
198 | + | ||
199 | + /** | ||
200 | + * We have received a fresh hello from a neighbor, now we need to process it. | ||
201 | + * Depending on the values received in the the hello options may force a | ||
202 | + * re-election process. | ||
203 | + * | ||
204 | + * We will also refresh the timeout for this neighbor. | ||
205 | + * | ||
206 | + * @param hello copy of the hello we'll be able to extract options from. | ||
207 | + */ | ||
208 | + public void refresh(PIMHello hello) { | ||
209 | + checkNotNull(hello); | ||
210 | + | ||
211 | + for (PIMHelloOption opt : hello.getOptions().values()) { | ||
212 | + | ||
213 | + int len = opt.getOptLength(); | ||
214 | + byte [] value = new byte[len]; | ||
215 | + ByteBuffer bb = ByteBuffer.wrap(value); | ||
216 | + | ||
217 | + switch (opt.getOptType()) { | ||
218 | + case PIMHelloOption.OPT_GENID: | ||
219 | + int newid = bb.getInt(); | ||
220 | + if (this.genId != newid) { | ||
221 | + // TODO: we have a newly rebooted neighbor. Send them our joins. | ||
222 | + this.genId = newid; | ||
223 | + } | ||
224 | + break; | ||
225 | + | ||
226 | + case PIMHelloOption.OPT_PRIORITY: | ||
227 | + int newpri = bb.getInt(); | ||
228 | + if (this.priority != newpri) { | ||
229 | + | ||
230 | + // The priorities have changed. We may need to re-elect a new DR? | ||
231 | + if (this.isDr || this.neighbors.getDesignatedRouter().getPriority() < priority) { | ||
232 | + reelect = true; | ||
233 | + } | ||
234 | + this.priority = newpri; | ||
235 | + } | ||
236 | + break; | ||
237 | + | ||
238 | + case PIMHelloOption.OPT_HOLDTIME: | ||
239 | + short holdtime = bb.getShort(); | ||
240 | + if (this.holdtime != holdtime) { | ||
241 | + this.holdtime = holdtime; | ||
242 | + if (holdtime == 0) { | ||
243 | + // We have a neighbor going down. We can remove all joins | ||
244 | + // we have learned from them. | ||
245 | + // TODO: What else do we need to do when a neighbor goes down? | ||
246 | + | ||
247 | + log.debug("PIM Neighbor has timed out: {}", this.primaryAddr.toString()); | ||
248 | + return; | ||
249 | + } | ||
250 | + } | ||
251 | + break; | ||
252 | + | ||
253 | + case PIMHelloOption.OPT_PRUNEDELAY: | ||
254 | + case PIMHelloOption.OPT_ADDRLIST: | ||
255 | + // TODO: implement prune delay and addr list. Fall through for now. | ||
256 | + | ||
257 | + default: | ||
258 | + log.debug("PIM Hello option type: {} not yet supported or unknown.", opt.getOptType()); | ||
259 | + break; | ||
260 | + } | ||
261 | + } | ||
262 | + | ||
263 | + if (reelect) { | ||
264 | + this.neighbors.electDR(this); | ||
265 | + } | ||
266 | + | ||
267 | + // Reset the next timeout timer | ||
268 | + this.resetTimeout(); | ||
269 | + } | ||
270 | + | ||
271 | + /* --------------------------------------- Timer functions -------------------------- */ | ||
272 | + | ||
273 | + /** | ||
274 | + * Restart the timeout task for this neighbor. | ||
275 | + */ | ||
276 | + private void resetTimeout() { | ||
277 | + | ||
278 | + if (this.holdtime == 0) { | ||
279 | + | ||
280 | + // Prepare to die. | ||
281 | + log.debug("shutting down timer for nbr {}", this.primaryAddr.toString()); | ||
282 | + if (this.timeout != null) { | ||
283 | + this.timeout.cancel(); | ||
284 | + this.timeout = null; | ||
285 | + } | ||
286 | + return; | ||
287 | + } | ||
288 | + | ||
289 | + // Cancel the existing timeout and start a fresh new one. | ||
290 | + if (this.timeout != null) { | ||
291 | + this.timeout.cancel(); | ||
292 | + } | ||
293 | + | ||
294 | + this.timeout = PIMTimer.getTimer().newTimeout(new NeighborTimeoutTask(this), holdtime, TimeUnit.SECONDS); | ||
295 | + } | ||
296 | + | ||
297 | + /** | ||
298 | + * The task to run when a neighbor timeout expires. | ||
299 | + */ | ||
300 | + private final class NeighborTimeoutTask implements TimerTask { | ||
301 | + PIMNeighbor nbr; | ||
302 | + | ||
303 | + NeighborTimeoutTask(PIMNeighbor nbr) { | ||
304 | + this.nbr = nbr; | ||
305 | + } | ||
306 | + | ||
307 | + @Override | ||
308 | + public void run(Timeout timeout) throws Exception { | ||
309 | + | ||
310 | + // TODO: log.debug; | ||
311 | + PIMNeighbors neighbors = nbr.neighbors; | ||
312 | + neighbors.removeNeighbor(nbr.getPrimaryAddr()); | ||
313 | + } | ||
314 | + } | ||
315 | + | ||
316 | + /** | ||
317 | + * Stop the timeout timer. | ||
318 | + * | ||
319 | + * This happens when we remove the neighbor. | ||
320 | + */ | ||
321 | + private final void stopTimeout() { | ||
322 | + this.timeout.cancel(); | ||
323 | + this.timeout = null; | ||
324 | + } | ||
325 | + | ||
326 | + @Override | ||
327 | + public String toString() { | ||
328 | + String out = ""; | ||
329 | + if (this.isDr) { | ||
330 | + out += "*NBR:"; | ||
331 | + } else { | ||
332 | + out += "NBR:"; | ||
333 | + } | ||
334 | + out += "\tIP: " + this.primaryAddr.toString(); | ||
335 | + out += "\tPr: " + String.valueOf(this.priority); | ||
336 | + out += "\tHoldTime: " + String.valueOf(this.holdtime); | ||
337 | + out += "\tGenID: " + String.valueOf(this.genId) + "\n"; | ||
338 | + return out; | ||
339 | + } | ||
340 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
This diff is collapsed. Click to expand it.
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pim.impl; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | +import org.onosproject.codec.CodecContext; | ||
21 | +import org.onosproject.codec.JsonCodec; | ||
22 | +import org.onosproject.net.ConnectPoint; | ||
23 | + | ||
24 | +import java.util.HashMap; | ||
25 | + | ||
26 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
27 | + | ||
28 | +/** | ||
29 | + * PIM neighbors Codec. | ||
30 | + */ | ||
31 | +public class PIMNeighborsCodec extends JsonCodec<HashMap<ConnectPoint, PIMNeighbors>> { | ||
32 | + // JSON field names | ||
33 | + //Return Name | ||
34 | + private static final String CPNBRLIST = "connect_point_list"; | ||
35 | + | ||
36 | + // PIM Neightbors Fields | ||
37 | + private static final String IP = "ip"; | ||
38 | + private static final String PRIORITY = "priority"; | ||
39 | + private static final String NBRLIST = "neighbor_list"; | ||
40 | + | ||
41 | + // PIM neighbor Files | ||
42 | + private static final String DR = "designated"; | ||
43 | + private static final String NBR_IP = "ip"; | ||
44 | + private static final String PR = "priority"; | ||
45 | + private static final String HOLDTIME = "hold_time"; | ||
46 | + | ||
47 | + /** | ||
48 | + * Encode the PIM Neighbors. | ||
49 | + * | ||
50 | + * @param cpn ConnectPoint neighbors | ||
51 | + * @param context encoding context | ||
52 | + * | ||
53 | + * @return Encoded neighbors used by CLI and REST | ||
54 | + */ | ||
55 | + @Override | ||
56 | + public ObjectNode encode(HashMap<ConnectPoint, PIMNeighbors> cpn, CodecContext context) { | ||
57 | + checkNotNull(cpn, "Pim Neighbors cannot be null"); | ||
58 | + | ||
59 | + ObjectNode pimNbrJsonCodec = context.mapper().createObjectNode(); | ||
60 | + ArrayNode cpnList = context.mapper().createArrayNode(); | ||
61 | + | ||
62 | + for (PIMNeighbors pn: cpn.values()) { | ||
63 | + // get the PimNeighbors Obj, contains Neighbors list | ||
64 | + // create the json object for a single Entry in the Neighbors list | ||
65 | + ObjectNode cp = context.mapper().createObjectNode(); | ||
66 | + cp.put(IP, pn.getOurIpAddress().toString()); | ||
67 | + cp.put(PRIORITY, String.valueOf(pn.getOurPriority())); | ||
68 | + | ||
69 | + // create the array for the neighbors list | ||
70 | + ArrayNode nbrsList = context.mapper().createArrayNode(); | ||
71 | + for (PIMNeighbor nbr : pn.getOurNeighborsList().values()) { | ||
72 | + nbrsList.add(neighbor(nbr, context)); | ||
73 | + } | ||
74 | + // adds pim neighbor to list | ||
75 | + cp.set(NBRLIST, nbrsList); | ||
76 | + // adds to arraynode which will represent the connect point neighbors hash map. | ||
77 | + cpnList.add(cp); | ||
78 | + } | ||
79 | + pimNbrJsonCodec.set(CPNBRLIST, cpnList); | ||
80 | + return pimNbrJsonCodec; | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * Encode a single PIM Neighbor. | ||
85 | + * | ||
86 | + * @param nbr the neighbor to be encoded | ||
87 | + * @param context encoding context | ||
88 | + * @return the encoded neighbor | ||
89 | + */ | ||
90 | + private ObjectNode neighbor(PIMNeighbor nbr, CodecContext context) { | ||
91 | + return context.mapper().createObjectNode() | ||
92 | + .put(DR, Boolean.toString(nbr.isDr())) | ||
93 | + .put(NBR_IP, nbr.getPrimaryAddr().toString()) | ||
94 | + .put(PR, String.valueOf(nbr.getPriority())) | ||
95 | + .put(HOLDTIME, String.valueOf(nbr.getHoldtime())); | ||
96 | + } | ||
97 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pim.impl; | ||
17 | + | ||
18 | +import org.jboss.netty.util.HashedWheelTimer; | ||
19 | + | ||
20 | +/** | ||
21 | + * PIM Timer used for PIM Neighbors. | ||
22 | + */ | ||
23 | +public final class PIMTimer { | ||
24 | + | ||
25 | + private static volatile HashedWheelTimer timer; | ||
26 | + | ||
27 | + // Ban public construction | ||
28 | + private PIMTimer() { | ||
29 | + } | ||
30 | + | ||
31 | + /** | ||
32 | + * Returns the singleton hashed-wheel timer. | ||
33 | + * | ||
34 | + * @return hashed-wheel timer | ||
35 | + */ | ||
36 | + public static HashedWheelTimer getTimer() { | ||
37 | + if (PIMTimer.timer == null) { | ||
38 | + initTimer(); | ||
39 | + } | ||
40 | + return PIMTimer.timer; | ||
41 | + } | ||
42 | + | ||
43 | + // Start the PIM timer. | ||
44 | + private static synchronized void initTimer() { | ||
45 | + if (PIMTimer.timer == null) { | ||
46 | + | ||
47 | + // Create and start a new hashed wheel timer, if it does not exist. | ||
48 | + HashedWheelTimer hwTimer = new HashedWheelTimer(); | ||
49 | + hwTimer.start(); | ||
50 | + PIMTimer.timer = hwTimer; | ||
51 | + } | ||
52 | + } | ||
53 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/** | ||
18 | + * PIM Emulation speak hello messages and listen to Join/Prunes. | ||
19 | + */ | ||
20 | +package org.onosproject.pim.impl; |
1 | +<!-- | ||
2 | + ~ Copyright 2015 Open Networking Laboratory | ||
3 | + ~ | ||
4 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + ~ you may not use this file except in compliance with the License. | ||
6 | + ~ You may obtain a copy of the License at | ||
7 | + ~ | ||
8 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + ~ | ||
10 | + ~ Unless required by applicable law or agreed to in writing, software | ||
11 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + ~ See the License for the specific language governing permissions and | ||
14 | + ~ limitations under the License. | ||
15 | + --> | ||
16 | +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> | ||
17 | + | ||
18 | + <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> | ||
19 | + <command> | ||
20 | + <action class="org.onosproject.pim.cli.PIMShowCommand"/> | ||
21 | + </command> | ||
22 | + </command-bundle> | ||
23 | + | ||
24 | +</blueprint> |
... | @@ -58,6 +58,9 @@ | ... | @@ -58,6 +58,9 @@ |
58 | <module>vtnweb</module> | 58 | <module>vtnweb</module> |
59 | <module>dhcp</module> | 59 | <module>dhcp</module> |
60 | <module>cordvtn</module> | 60 | <module>cordvtn</module> |
61 | + <module>mfwd</module> | ||
62 | + <module>igmp</module> | ||
63 | + <module>pim</module> | ||
61 | </modules> | 64 | </modules> |
62 | 65 | ||
63 | <properties> | 66 | <properties> | ... | ... |
-
Please register or login to post a comment