Committed by
Gerrit Code Review
WIP: proxy NDP for IPv6.
ONOS-924 Need to implement test cases. Change-Id: I86b0cb8c3c8d75f7276778e04c1a7166c9bb2f59
Showing
8 changed files
with
368 additions
and
33 deletions
... | @@ -37,6 +37,7 @@ | ... | @@ -37,6 +37,7 @@ |
37 | <module>ifwd</module> | 37 | <module>ifwd</module> |
38 | <module>mobility</module> | 38 | <module>mobility</module> |
39 | <module>proxyarp</module> | 39 | <module>proxyarp</module> |
40 | + <module>proxyndp</module> | ||
40 | <module>config</module> | 41 | <module>config</module> |
41 | <module>sdnip</module> | 42 | <module>sdnip</module> |
42 | <module>calendar</module> | 43 | <module>calendar</module> | ... | ... |
apps/proxyndp/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.1.0-SNAPSHOT</version> | ||
26 | + <relativePath>../pom.xml</relativePath> | ||
27 | + </parent> | ||
28 | + | ||
29 | + <artifactId>onos-app-proxyndp</artifactId> | ||
30 | + <packaging>bundle</packaging> | ||
31 | + | ||
32 | + <description>ONOS simple proxy neighbor discovery for IPv6 module</description> | ||
33 | + | ||
34 | +</project> |
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 | +package org.onosproject.proxyndp; | ||
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.IPv6; | ||
27 | +import org.onlab.packet.ICMP6; | ||
28 | +import org.onosproject.core.ApplicationId; | ||
29 | +import org.onosproject.core.CoreService; | ||
30 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
31 | +import org.onosproject.net.flow.TrafficSelector; | ||
32 | +import org.onosproject.net.packet.PacketContext; | ||
33 | +import org.onosproject.net.packet.PacketPriority; | ||
34 | +import org.onosproject.net.packet.PacketProcessor; | ||
35 | +import org.onosproject.net.packet.PacketService; | ||
36 | +import org.onosproject.net.proxyarp.ProxyArpService; | ||
37 | +import org.slf4j.Logger; | ||
38 | + | ||
39 | +/** | ||
40 | + * Sample reactive proxy ndp application. | ||
41 | + */ | ||
42 | +@Component(immediate = true) | ||
43 | +public class ProxyNdp { | ||
44 | + | ||
45 | + private final Logger log = getLogger(getClass()); | ||
46 | + | ||
47 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
48 | + protected PacketService packetService; | ||
49 | + | ||
50 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
51 | + protected ProxyArpService proxyArpService; | ||
52 | + | ||
53 | + private ProxyNdpProcessor processor = new ProxyNdpProcessor(); | ||
54 | + | ||
55 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
56 | + protected CoreService coreService; | ||
57 | + | ||
58 | + private ApplicationId appId; | ||
59 | + | ||
60 | + @Activate | ||
61 | + public void activate() { | ||
62 | + appId = coreService.registerApplication("org.onosproject.proxyndp"); | ||
63 | + packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1); | ||
64 | + | ||
65 | + TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); | ||
66 | + selectorBuilder.matchEthType(Ethernet.TYPE_IPV6); | ||
67 | + selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6); | ||
68 | + selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION); | ||
69 | + packetService.requestPackets(selectorBuilder.build(), | ||
70 | + PacketPriority.CONTROL, appId); | ||
71 | + | ||
72 | + selectorBuilder = DefaultTrafficSelector.builder(); | ||
73 | + selectorBuilder.matchEthType(Ethernet.TYPE_IPV6); | ||
74 | + selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6); | ||
75 | + selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT); | ||
76 | + packetService.requestPackets(selectorBuilder.build(), | ||
77 | + PacketPriority.CONTROL, appId); | ||
78 | + | ||
79 | + log.info("Started with Application ID {}", appId.id()); | ||
80 | + } | ||
81 | + | ||
82 | + @Deactivate | ||
83 | + public void deactivate() { | ||
84 | + packetService.removeProcessor(processor); | ||
85 | + processor = null; | ||
86 | + log.info("Stopped"); | ||
87 | + } | ||
88 | + | ||
89 | + | ||
90 | + /** | ||
91 | + * Packet processor responsible for forwarding packets along their paths. | ||
92 | + */ | ||
93 | + private class ProxyNdpProcessor implements PacketProcessor { | ||
94 | + | ||
95 | + @Override | ||
96 | + public void process(PacketContext context) { | ||
97 | + // Stop processing if the packet has been handled, since we | ||
98 | + // can't do any more to it. | ||
99 | + if (context.isHandled()) { | ||
100 | + return; | ||
101 | + } | ||
102 | + | ||
103 | + // Handle the neighbor discovery packet. | ||
104 | + proxyArpService.handlePacket(context); | ||
105 | + } | ||
106 | + } | ||
107 | +} | ||
108 | + | ||
109 | + |
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 | + | ||
17 | +/** | ||
18 | + * Proxy Ndp application that handles IPv6 neighbor resolution for you. | ||
19 | + */ | ||
20 | +package org.onosproject.proxyndp; |
... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
16 | package org.onosproject.net.proxyarp; | 16 | package org.onosproject.net.proxyarp; |
17 | 17 | ||
18 | import org.onlab.packet.Ethernet; | 18 | import org.onlab.packet.Ethernet; |
19 | -import org.onlab.packet.Ip4Address; | 19 | +import org.onlab.packet.IpAddress; |
20 | import org.onosproject.net.ConnectPoint; | 20 | import org.onosproject.net.ConnectPoint; |
21 | import org.onosproject.net.packet.PacketContext; | 21 | import org.onosproject.net.packet.PacketContext; |
22 | 22 | ||
... | @@ -27,37 +27,39 @@ import org.onosproject.net.packet.PacketContext; | ... | @@ -27,37 +27,39 @@ import org.onosproject.net.packet.PacketContext; |
27 | public interface ProxyArpService { | 27 | public interface ProxyArpService { |
28 | 28 | ||
29 | /** | 29 | /** |
30 | - * Returns whether this particular IPv4 address is known to the system. | 30 | + * Returns whether this particular IP address is known to the system. |
31 | * | 31 | * |
32 | - * @param addr an IPv4 address | 32 | + * @param addr an IP address |
33 | * @return true if know, false otherwise | 33 | * @return true if know, false otherwise |
34 | */ | 34 | */ |
35 | - boolean isKnown(Ip4Address addr); | 35 | + boolean isKnown(IpAddress addr); |
36 | 36 | ||
37 | /** | 37 | /** |
38 | - * Sends a reply for a given request. If the host is not known then the arp | 38 | + * Sends a reply for a given request. If the host is not known then the |
39 | - * will be flooded at all edge ports. | 39 | + * arp or neighbor solicitation will be flooded at all edge ports. |
40 | * | 40 | * |
41 | - * @param eth an arp request | 41 | + * @param eth an arp or neighbor solicitation request |
42 | * @param inPort the port the request was received on | 42 | * @param inPort the port the request was received on |
43 | */ | 43 | */ |
44 | void reply(Ethernet eth, ConnectPoint inPort); | 44 | void reply(Ethernet eth, ConnectPoint inPort); |
45 | 45 | ||
46 | /** | 46 | /** |
47 | - * Forwards an ARP request to its destination. Floods at the edge the ARP request if the | 47 | + * Forwards an ARP or neighbor solicitation request to its destination. |
48 | - * destination is not known. | 48 | + * Floods at the edg the request if the destination is not known. |
49 | * | 49 | * |
50 | - * @param eth an ethernet frame containing an ARP request. | 50 | + * @param eth an ethernet frame containing an ARP or neighbor solicitation |
51 | + * request. | ||
51 | * @param inPort the port the request was received on | 52 | * @param inPort the port the request was received on |
52 | */ | 53 | */ |
53 | void forward(Ethernet eth, ConnectPoint inPort); | 54 | void forward(Ethernet eth, ConnectPoint inPort); |
54 | 55 | ||
55 | /** | 56 | /** |
56 | - * Handles a arp packet. | 57 | + * Handles a arp or neighbor solicitation packet. |
57 | - * Replies to arp requests and forwards request to the right place. | 58 | + * Replies to arp or neighbor solicitation requests and forwards request |
59 | + * to the right place. | ||
58 | * @param context the packet context to handle | 60 | * @param context the packet context to handle |
59 | * @return true if handled, false otherwise. | 61 | * @return true if handled, false otherwise. |
60 | */ | 62 | */ |
61 | - boolean handleArp(PacketContext context); | 63 | + boolean handlePacket(PacketContext context); |
62 | 64 | ||
63 | } | 65 | } | ... | ... |
... | @@ -26,10 +26,15 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -26,10 +26,15 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
26 | import org.apache.felix.scr.annotations.Service; | 26 | import org.apache.felix.scr.annotations.Service; |
27 | import org.onlab.packet.ARP; | 27 | import org.onlab.packet.ARP; |
28 | import org.onlab.packet.Ethernet; | 28 | import org.onlab.packet.Ethernet; |
29 | +import org.onlab.packet.ICMP6; | ||
30 | +import org.onlab.packet.IPv6; | ||
29 | import org.onlab.packet.Ip4Address; | 31 | import org.onlab.packet.Ip4Address; |
32 | +import org.onlab.packet.Ip6Address; | ||
30 | import org.onlab.packet.IpAddress; | 33 | import org.onlab.packet.IpAddress; |
31 | import org.onlab.packet.MacAddress; | 34 | import org.onlab.packet.MacAddress; |
32 | import org.onlab.packet.VlanId; | 35 | import org.onlab.packet.VlanId; |
36 | +import org.onlab.packet.ndp.NeighborAdvertisement; | ||
37 | +import org.onlab.packet.ndp.NeighborSolicitation; | ||
33 | import org.onosproject.net.ConnectPoint; | 38 | import org.onosproject.net.ConnectPoint; |
34 | import org.onosproject.net.Device; | 39 | import org.onosproject.net.Device; |
35 | import org.onosproject.net.Host; | 40 | import org.onosproject.net.Host; |
... | @@ -72,7 +77,7 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -72,7 +77,7 @@ public class ProxyArpManager implements ProxyArpService { |
72 | private final Logger log = getLogger(getClass()); | 77 | private final Logger log = getLogger(getClass()); |
73 | 78 | ||
74 | private static final String MAC_ADDR_NULL = "Mac address cannot be null."; | 79 | private static final String MAC_ADDR_NULL = "Mac address cannot be null."; |
75 | - private static final String REQUEST_NULL = "Arp request cannot be null."; | 80 | + private static final String REQUEST_NULL = "ARP or NDP request cannot be null."; |
76 | private static final String REQUEST_NOT_ARP = "Ethernet frame does not contain ARP request."; | 81 | private static final String REQUEST_NOT_ARP = "Ethernet frame does not contain ARP request."; |
77 | private static final String NOT_ARP_REQUEST = "ARP is not a request."; | 82 | private static final String NOT_ARP_REQUEST = "ARP is not a request."; |
78 | private static final String NOT_ARP_REPLY = "ARP is not a reply."; | 83 | private static final String NOT_ARP_REPLY = "ARP is not a reply."; |
... | @@ -115,7 +120,7 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -115,7 +120,7 @@ public class ProxyArpManager implements ProxyArpService { |
115 | } | 120 | } |
116 | 121 | ||
117 | @Override | 122 | @Override |
118 | - public boolean isKnown(Ip4Address addr) { | 123 | + public boolean isKnown(IpAddress addr) { |
119 | checkNotNull(addr, MAC_ADDR_NULL); | 124 | checkNotNull(addr, MAC_ADDR_NULL); |
120 | Set<Host> hosts = hostService.getHostsByIp(addr); | 125 | Set<Host> hosts = hostService.getHostsByIp(addr); |
121 | return !hosts.isEmpty(); | 126 | return !hosts.isEmpty(); |
... | @@ -124,8 +129,15 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -124,8 +129,15 @@ public class ProxyArpManager implements ProxyArpService { |
124 | @Override | 129 | @Override |
125 | public void reply(Ethernet eth, ConnectPoint inPort) { | 130 | public void reply(Ethernet eth, ConnectPoint inPort) { |
126 | checkNotNull(eth, REQUEST_NULL); | 131 | checkNotNull(eth, REQUEST_NULL); |
127 | - checkArgument(eth.getEtherType() == Ethernet.TYPE_ARP, | 132 | + |
128 | - REQUEST_NOT_ARP); | 133 | + if (eth.getEtherType() == Ethernet.TYPE_ARP) { |
134 | + replyArp(eth, inPort); | ||
135 | + } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) { | ||
136 | + replyNdp(eth, inPort); | ||
137 | + } | ||
138 | + } | ||
139 | + | ||
140 | + private void replyArp(Ethernet eth, ConnectPoint inPort) { | ||
129 | ARP arp = (ARP) eth.getPayload(); | 141 | ARP arp = (ARP) eth.getPayload(); |
130 | checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST); | 142 | checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST); |
131 | checkNotNull(inPort); | 143 | checkNotNull(inPort); |
... | @@ -209,6 +221,92 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -209,6 +221,92 @@ public class ProxyArpManager implements ProxyArpService { |
209 | } | 221 | } |
210 | } | 222 | } |
211 | 223 | ||
224 | + private void replyNdp(Ethernet eth, ConnectPoint inPort) { | ||
225 | + | ||
226 | + IPv6 ipv6 = (IPv6) eth.getPayload(); | ||
227 | + ICMP6 icmpv6 = (ICMP6) ipv6.getPayload(); | ||
228 | + NeighborSolicitation nsol = (NeighborSolicitation) icmpv6.getPayload(); | ||
229 | + | ||
230 | + VlanId vlan = VlanId.vlanId(eth.getVlanID()); | ||
231 | + | ||
232 | + // If the request came from outside the network, only reply if it was | ||
233 | + // for one of our external addresses. | ||
234 | + if (isOutsidePort(inPort)) { | ||
235 | + Ip6Address target = | ||
236 | + Ip6Address.valueOf(nsol.getTargetAddress()); | ||
237 | + Set<PortAddresses> addressSet = | ||
238 | + hostService.getAddressBindingsForPort(inPort); | ||
239 | + | ||
240 | + for (PortAddresses addresses : addressSet) { | ||
241 | + for (InterfaceIpAddress ia : addresses.ipAddresses()) { | ||
242 | + if (ia.ipAddress().equals(target)) { | ||
243 | + Ethernet ndpReply = | ||
244 | + buildNdpReply(target, addresses.mac(), eth); | ||
245 | + sendTo(ndpReply, inPort); | ||
246 | + } | ||
247 | + } | ||
248 | + } | ||
249 | + return; | ||
250 | + } else { | ||
251 | + // If the source address matches one of our external addresses | ||
252 | + // it could be a request from an internal host to an external | ||
253 | + // address. Forward it over to the correct ports. | ||
254 | + Ip6Address source = | ||
255 | + Ip6Address.valueOf(nsol.getTargetAddress()); | ||
256 | + Set<PortAddresses> sourceAddresses = findPortsInSubnet(source); | ||
257 | + boolean matched = false; | ||
258 | + for (PortAddresses pa : sourceAddresses) { | ||
259 | + for (InterfaceIpAddress ia : pa.ipAddresses()) { | ||
260 | + if (ia.ipAddress().equals(source) && | ||
261 | + pa.vlan().equals(vlan)) { | ||
262 | + matched = true; | ||
263 | + sendTo(eth, pa.connectPoint()); | ||
264 | + } | ||
265 | + } | ||
266 | + } | ||
267 | + | ||
268 | + if (matched) { | ||
269 | + return; | ||
270 | + } | ||
271 | + } | ||
272 | + | ||
273 | + // Continue with normal proxy ARP case | ||
274 | + | ||
275 | + Set<Host> hosts = hostService.getHostsByIp( | ||
276 | + Ip6Address.valueOf(nsol.getTargetAddress())); | ||
277 | + | ||
278 | + Host dst = null; | ||
279 | + Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(), | ||
280 | + VlanId.vlanId(eth.getVlanID()))); | ||
281 | + | ||
282 | + for (Host host : hosts) { | ||
283 | + if (host.vlan().equals(vlan)) { | ||
284 | + dst = host; | ||
285 | + break; | ||
286 | + } | ||
287 | + } | ||
288 | + | ||
289 | + if (src == null || dst == null) { | ||
290 | + flood(eth, inPort); | ||
291 | + return; | ||
292 | + } | ||
293 | + | ||
294 | + // | ||
295 | + // TODO find the correct IP address. | ||
296 | + // Right now we use the first IPv4 address that is found. | ||
297 | + // | ||
298 | + for (IpAddress ipAddress : dst.ipAddresses()) { | ||
299 | + Ip6Address ip6Address = ipAddress.getIp6Address(); | ||
300 | + if (ip6Address != null) { | ||
301 | + Ethernet arpReply = buildNdpReply(ip6Address, dst.mac(), eth); | ||
302 | + // TODO: check send status with host service. | ||
303 | + sendTo(arpReply, src.location()); | ||
304 | + break; | ||
305 | + } | ||
306 | + } | ||
307 | + } | ||
308 | + | ||
309 | + | ||
212 | /** | 310 | /** |
213 | * Outputs the given packet out the given port. | 311 | * Outputs the given packet out the given port. |
214 | * | 312 | * |
... | @@ -236,7 +334,7 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -236,7 +334,7 @@ public class ProxyArpManager implements ProxyArpService { |
236 | * @param target the target address to find a matching port for | 334 | * @param target the target address to find a matching port for |
237 | * @return a set of PortAddresses describing ports in the subnet | 335 | * @return a set of PortAddresses describing ports in the subnet |
238 | */ | 336 | */ |
239 | - private Set<PortAddresses> findPortsInSubnet(Ip4Address target) { | 337 | + private Set<PortAddresses> findPortsInSubnet(IpAddress target) { |
240 | Set<PortAddresses> result = new HashSet<PortAddresses>(); | 338 | Set<PortAddresses> result = new HashSet<PortAddresses>(); |
241 | for (PortAddresses addresses : hostService.getAddressBindings()) { | 339 | for (PortAddresses addresses : hostService.getAddressBindings()) { |
242 | for (InterfaceIpAddress ia : addresses.ipAddresses()) { | 340 | for (InterfaceIpAddress ia : addresses.ipAddresses()) { |
... | @@ -266,10 +364,6 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -266,10 +364,6 @@ public class ProxyArpManager implements ProxyArpService { |
266 | @Override | 364 | @Override |
267 | public void forward(Ethernet eth, ConnectPoint inPort) { | 365 | public void forward(Ethernet eth, ConnectPoint inPort) { |
268 | checkNotNull(eth, REQUEST_NULL); | 366 | checkNotNull(eth, REQUEST_NULL); |
269 | - checkArgument(eth.getEtherType() == Ethernet.TYPE_ARP, | ||
270 | - REQUEST_NOT_ARP); | ||
271 | - ARP arp = (ARP) eth.getPayload(); | ||
272 | - checkArgument(arp.getOpCode() == ARP.OP_REPLY, NOT_ARP_REPLY); | ||
273 | 367 | ||
274 | Host h = hostService.getHost(HostId.hostId(eth.getDestinationMAC(), | 368 | Host h = hostService.getHost(HostId.hostId(eth.getDestinationMAC(), |
275 | VlanId.vlanId(eth.getVlanID()))); | 369 | VlanId.vlanId(eth.getVlanID()))); |
... | @@ -286,22 +380,53 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -286,22 +380,53 @@ public class ProxyArpManager implements ProxyArpService { |
286 | } | 380 | } |
287 | 381 | ||
288 | @Override | 382 | @Override |
289 | - public boolean handleArp(PacketContext context) { | 383 | + public boolean handlePacket(PacketContext context) { |
290 | InboundPacket pkt = context.inPacket(); | 384 | InboundPacket pkt = context.inPacket(); |
291 | Ethernet ethPkt = pkt.parsed(); | 385 | Ethernet ethPkt = pkt.parsed(); |
292 | - if (ethPkt != null && ethPkt.getEtherType() == Ethernet.TYPE_ARP) { | 386 | + |
293 | - ARP arp = (ARP) ethPkt.getPayload(); | 387 | + if (ethPkt == null) { |
294 | - if (arp.getOpCode() == ARP.OP_REPLY) { | 388 | + return false; |
295 | - forward(ethPkt, context.inPacket().receivedFrom()); | 389 | + } |
296 | - } else if (arp.getOpCode() == ARP.OP_REQUEST) { | 390 | + if (ethPkt.getEtherType() == Ethernet.TYPE_ARP) { |
297 | - reply(ethPkt, context.inPacket().receivedFrom()); | 391 | + return handleArp(context, ethPkt); |
298 | - } | 392 | + } else if (ethPkt.getEtherType() == Ethernet.TYPE_IPV6) { |
299 | - context.block(); | 393 | + return handleNdp(context, ethPkt); |
300 | - return true; | ||
301 | } | 394 | } |
302 | return false; | 395 | return false; |
303 | } | 396 | } |
304 | 397 | ||
398 | + private boolean handleArp(PacketContext context, Ethernet ethPkt) { | ||
399 | + ARP arp = (ARP) ethPkt.getPayload(); | ||
400 | + | ||
401 | + if (arp.getOpCode() == ARP.OP_REPLY) { | ||
402 | + forward(ethPkt, context.inPacket().receivedFrom()); | ||
403 | + } else if (arp.getOpCode() == ARP.OP_REQUEST) { | ||
404 | + reply(ethPkt, context.inPacket().receivedFrom()); | ||
405 | + } else { | ||
406 | + return false; | ||
407 | + } | ||
408 | + context.block(); | ||
409 | + return true; | ||
410 | + } | ||
411 | + | ||
412 | + private boolean handleNdp(PacketContext context, Ethernet ethPkt) { | ||
413 | + IPv6 ipv6 = (IPv6) ethPkt.getPayload(); | ||
414 | + | ||
415 | + if (ipv6.getNextHeader() != IPv6.PROTOCOL_ICMP6) { | ||
416 | + return false; | ||
417 | + } | ||
418 | + ICMP6 icmpv6 = (ICMP6) ipv6.getPayload(); | ||
419 | + if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_ADVERTISEMENT) { | ||
420 | + forward(ethPkt, context.inPacket().receivedFrom()); | ||
421 | + } else if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_SOLICITATION) { | ||
422 | + reply(ethPkt, context.inPacket().receivedFrom()); | ||
423 | + } else { | ||
424 | + return false; | ||
425 | + } | ||
426 | + context.block(); | ||
427 | + return true; | ||
428 | + } | ||
429 | + | ||
305 | /** | 430 | /** |
306 | * Flood the arp request at all edges in the network. | 431 | * Flood the arp request at all edges in the network. |
307 | * @param request the arp request. | 432 | * @param request the arp request. |
... | @@ -398,6 +523,44 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -398,6 +523,44 @@ public class ProxyArpManager implements ProxyArpService { |
398 | return eth; | 523 | return eth; |
399 | } | 524 | } |
400 | 525 | ||
526 | + /** | ||
527 | + * Builds an Neighbor Discovery reply based on a request. | ||
528 | + * | ||
529 | + * @param srcIp the IP address to use as the reply source | ||
530 | + * @param srcMac the MAC address to use as the reply source | ||
531 | + * @param request the Neighbor Solicitation request we got | ||
532 | + * @return an Ethernet frame containing the Neighbor Advertisement reply | ||
533 | + */ | ||
534 | + private Ethernet buildNdpReply(Ip6Address srcIp, MacAddress srcMac, | ||
535 | + Ethernet request) { | ||
536 | + | ||
537 | + Ethernet eth = new Ethernet(); | ||
538 | + eth.setDestinationMACAddress(request.getSourceMAC()); | ||
539 | + eth.setSourceMACAddress(srcMac); | ||
540 | + eth.setEtherType(Ethernet.TYPE_IPV6); | ||
541 | + eth.setVlanID(request.getVlanID()); | ||
542 | + | ||
543 | + IPv6 requestIp = (IPv6) request.getPayload(); | ||
544 | + IPv6 ipv6 = new IPv6(); | ||
545 | + ipv6.setSourceAddress(srcIp.toOctets()); | ||
546 | + ipv6.setDestinationAddress(requestIp.getSourceAddress()); | ||
547 | + ipv6.setHopLimit((byte) 255); | ||
548 | + eth.setPayload(ipv6); | ||
549 | + | ||
550 | + ICMP6 icmp6 = new ICMP6(); | ||
551 | + icmp6.setIcmpType(ICMP6.NEIGHBOR_ADVERTISEMENT); | ||
552 | + icmp6.setIcmpCode((byte) 0); | ||
553 | + ipv6.setPayload(icmp6); | ||
554 | + | ||
555 | + NeighborAdvertisement nadv = new NeighborAdvertisement(); | ||
556 | + nadv.setTargetAddress(srcMac.toBytes()); | ||
557 | + nadv.setSolicitedFlag((byte) 1); | ||
558 | + nadv.setOverrideFlag((byte) 1); | ||
559 | + icmp6.setPayload(nadv); | ||
560 | + | ||
561 | + return eth; | ||
562 | + } | ||
563 | + | ||
401 | public class InternalLinkListener implements LinkListener { | 564 | public class InternalLinkListener implements LinkListener { |
402 | 565 | ||
403 | @Override | 566 | @Override | ... | ... |
... | @@ -184,6 +184,12 @@ | ... | @@ -184,6 +184,12 @@ |
184 | <bundle>mvn:org.onosproject/onos-app-proxyarp/@ONOS-VERSION</bundle> | 184 | <bundle>mvn:org.onosproject/onos-app-proxyarp/@ONOS-VERSION</bundle> |
185 | </feature> | 185 | </feature> |
186 | 186 | ||
187 | + <feature name="onos-app-proxyndp" version="@FEATURE-VERSION" | ||
188 | + description="ONOS sample proxyndp application"> | ||
189 | + <feature>onos-api</feature> | ||
190 | + <bundle>mvn:org.onosproject/onos-app-proxyndp/@ONOS-VERSION</bundle> | ||
191 | + </feature> | ||
192 | + | ||
187 | <feature name="onos-app-foo" version="@FEATURE-VERSION" | 193 | <feature name="onos-app-foo" version="@FEATURE-VERSION" |
188 | description="ONOS sample playground application"> | 194 | description="ONOS sample playground application"> |
189 | <feature>onos-api</feature> | 195 | <feature>onos-api</feature> | ... | ... |
-
Please register or login to post a comment