Hyunsun Moon
Committed by Gerrit Code Review

Improved openstackSwitching ARP handler

Save REST calls by checking if the target IP is owned by a known host first.

Change-Id: Id1ac0e5e13d635b5216d50c7cafaed1179a7410e
...@@ -18,12 +18,14 @@ package org.onosproject.openstackswitching; ...@@ -18,12 +18,14 @@ package org.onosproject.openstackswitching;
18 import org.onlab.packet.ARP; 18 import org.onlab.packet.ARP;
19 import org.onlab.packet.Ethernet; 19 import org.onlab.packet.Ethernet;
20 import org.onlab.packet.Ip4Address; 20 import org.onlab.packet.Ip4Address;
21 +import org.onlab.packet.IpAddress;
21 import org.onlab.packet.MacAddress; 22 import org.onlab.packet.MacAddress;
23 +import org.onosproject.net.Host;
22 import org.onosproject.net.flow.DefaultTrafficTreatment; 24 import org.onosproject.net.flow.DefaultTrafficTreatment;
23 import org.onosproject.net.flow.TrafficTreatment; 25 import org.onosproject.net.flow.TrafficTreatment;
26 +import org.onosproject.net.host.HostService;
24 import org.onosproject.net.packet.DefaultOutboundPacket; 27 import org.onosproject.net.packet.DefaultOutboundPacket;
25 import org.onosproject.net.packet.InboundPacket; 28 import org.onosproject.net.packet.InboundPacket;
26 -import org.onosproject.net.packet.OutboundPacket;
27 import org.onosproject.net.packet.PacketService; 29 import org.onosproject.net.packet.PacketService;
28 import org.slf4j.Logger; 30 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory; 31 import org.slf4j.LoggerFactory;
...@@ -40,69 +42,106 @@ public class OpenstackArpHandler { ...@@ -40,69 +42,106 @@ public class OpenstackArpHandler {
40 .getLogger(OpenstackArpHandler.class); 42 .getLogger(OpenstackArpHandler.class);
41 private PacketService packetService; 43 private PacketService packetService;
42 private OpenstackRestHandler restHandler; 44 private OpenstackRestHandler restHandler;
45 + private HostService hostService;
43 46
44 /** 47 /**
45 * Returns OpenstackArpHandler reference. 48 * Returns OpenstackArpHandler reference.
46 * 49 *
47 * @param restHandler rest API handler reference 50 * @param restHandler rest API handler reference
48 * @param packetService PacketService reference 51 * @param packetService PacketService reference
52 + * @param hostService host service
49 */ 53 */
50 - public OpenstackArpHandler(OpenstackRestHandler restHandler, PacketService packetService) { 54 + public OpenstackArpHandler(OpenstackRestHandler restHandler, PacketService packetService,
55 + HostService hostService) {
51 this.restHandler = checkNotNull(restHandler); 56 this.restHandler = checkNotNull(restHandler);
52 this.packetService = packetService; 57 this.packetService = packetService;
58 + this.hostService = hostService;
53 } 59 }
54 60
55 /** 61 /**
56 - * Processes ARP packets. 62 + * Processes ARP request packets.
63 + * It checks if the target IP is owned by a known host first and then ask to
64 + * OpenStack if it's not. This ARP proxy does not support overlapping IP.
57 * 65 *
58 * @param pkt ARP request packet 66 * @param pkt ARP request packet
59 */ 67 */
60 public void processPacketIn(InboundPacket pkt) { 68 public void processPacketIn(InboundPacket pkt) {
61 - Ethernet ethernet = pkt.parsed(); 69 + Ethernet ethRequest = pkt.parsed();
62 - ARP arp = (ARP) ethernet.getPayload(); 70 + ARP arp = (ARP) ethRequest.getPayload();
63 71
64 - if (arp.getOpCode() == ARP.OP_REQUEST) { 72 + if (arp.getOpCode() != ARP.OP_REQUEST) {
65 - byte[] srcMacAddress = arp.getSenderHardwareAddress(); 73 + return;
66 - byte[] srcIPAddress = arp.getSenderProtocolAddress(); 74 + }
67 - byte[] dstIPAddress = arp.getTargetProtocolAddress(); 75 +
76 + IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
77 + MacAddress dstMac = getMacFromHostService(targetIp);
78 + if (dstMac == null) {
79 + dstMac = getMacFromOpenstack(targetIp);
80 + }
81 +
82 + if (dstMac == null) {
83 + log.debug("Failed to find MAC address for {}", targetIp.toString());
84 + return;
85 + }
86 +
87 + Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
88 + dstMac,
89 + ethRequest);
90 +
91 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
92 + .setOutput(pkt.receivedFrom().port())
93 + .build();
94 +
95 + packetService.emit(new DefaultOutboundPacket(
96 + pkt.receivedFrom().deviceId(),
97 + treatment,
98 + ByteBuffer.wrap(ethReply.serialize())));
99 + }
68 100
69 - //Searches the Dst MAC Address based on openstackPortMap 101 + /**
70 - MacAddress macAddress = null; 102 + * Returns MAC address of a host with a given target IP address by asking to
103 + * OpenStack. It does not support overlapping IP.
104 + *
105 + * @param targetIp target ip address
106 + * @return mac address, or null if it fails to fetch the mac
107 + */
108 + private MacAddress getMacFromOpenstack(IpAddress targetIp) {
109 + checkNotNull(targetIp);
71 110
72 - OpenstackPort openstackPort = restHandler.getPorts().stream(). 111 + OpenstackPort openstackPort = restHandler.getPorts()
73 - filter(e -> e.fixedIps().containsValue(Ip4Address.valueOf( 112 + .stream()
74 - dstIPAddress))).findAny().orElse(null); 113 + .filter(port -> port.fixedIps().containsValue(targetIp))
114 + .findFirst()
115 + .orElse(null);
75 116
76 if (openstackPort != null) { 117 if (openstackPort != null) {
77 - macAddress = openstackPort.macAddress(); 118 + log.debug("Found MAC from OpenStack for {}", targetIp.toString());
78 - log.debug("Found MACAddress: {}", macAddress.toString()); 119 + return openstackPort.macAddress();
79 } else { 120 } else {
80 - return; 121 + return null;
122 + }
81 } 123 }
82 124
83 - //Creates a response packet 125 + /**
84 - ARP arpReply = new ARP(); 126 + * Returns MAC address of a host with a given target IP address by asking to
85 - arpReply.setOpCode(ARP.OP_REPLY) 127 + * host service. It does not support overlapping IP.
86 - .setHardwareAddressLength(arp.getHardwareAddressLength()) 128 + *
87 - .setHardwareType(arp.getHardwareType()) 129 + * @param targetIp target ip
88 - .setProtocolAddressLength(arp.getProtocolAddressLength()) 130 + * @return mac address, or null if it fails to find the mac
89 - .setProtocolType(arp.getProtocolType()) 131 + */
90 - .setSenderHardwareAddress(macAddress.toBytes()) 132 + private MacAddress getMacFromHostService(IpAddress targetIp) {
91 - .setSenderProtocolAddress(dstIPAddress) 133 + checkNotNull(targetIp);
92 - .setTargetHardwareAddress(srcMacAddress) 134 +
93 - .setTargetProtocolAddress(srcIPAddress); 135 + Host host = hostService.getHostsByIp(targetIp)
94 - 136 + .stream()
95 - //Sends a response packet 137 + .findFirst()
96 - ethernet.setDestinationMACAddress(srcMacAddress) 138 + .orElse(null);
97 - .setSourceMACAddress(macAddress) 139 +
98 - .setEtherType(Ethernet.TYPE_ARP) 140 + if (host != null) {
99 - .setPayload(arpReply); 141 + log.debug("Found MAC from host service for {}", targetIp.toString());
100 - 142 + return host.mac();
101 - TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder(); 143 + } else {
102 - builder.setOutput(pkt.receivedFrom().port()); 144 + return null;
103 - OutboundPacket packet = new DefaultOutboundPacket(pkt.receivedFrom().deviceId(),
104 - builder.build(), ByteBuffer.wrap(ethernet.serialize()));
105 - packetService.emit(packet);
106 } 145 }
107 } 146 }
108 } 147 }
......
...@@ -394,7 +394,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -394,7 +394,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
394 InboundPacket pkt = context.inPacket(); 394 InboundPacket pkt = context.inPacket();
395 Ethernet ethernet = pkt.parsed(); 395 Ethernet ethernet = pkt.parsed();
396 396
397 - if (ethernet.getEtherType() == Ethernet.TYPE_ARP) { 397 + if (ethernet != null && ethernet.getEtherType() == Ethernet.TYPE_ARP) {
398 arpHandler.processPacketIn(pkt); 398 arpHandler.processPacketIn(pkt);
399 } 399 }
400 } 400 }
...@@ -483,7 +483,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -483,7 +483,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
483 } 483 }
484 doNotPushFlows = cfg.doNotPushFlows(); 484 doNotPushFlows = cfg.doNotPushFlows();
485 restHandler = new OpenstackRestHandler(cfg); 485 restHandler = new OpenstackRestHandler(cfg);
486 - arpHandler = new OpenstackArpHandler(restHandler, packetService); 486 + arpHandler = new OpenstackArpHandler(restHandler, packetService, hostService);
487 initializeFlowRules(); 487 initializeFlowRules();
488 } 488 }
489 489
......