Kunihiro Ishiguro
Committed by Gerrit Code Review

WIP: proxy NDP for IPv6.

ONOS-924

Need to implement test cases.

Change-Id: I86b0cb8c3c8d75f7276778e04c1a7166c9bb2f59
...@@ -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>
......
...@@ -91,7 +91,7 @@ public class ProxyArp { ...@@ -91,7 +91,7 @@ public class ProxyArp {
91 } 91 }
92 92
93 //handle the arp packet. 93 //handle the arp packet.
94 - proxyArpService.handleArp(context); 94 + proxyArpService.handlePacket(context);
95 } 95 }
96 } 96 }
97 } 97 }
......
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>
......