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
Showing
2 changed files
with
81 additions
and
42 deletions
... | @@ -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 | ... | ... |
-
Please register or login to post a comment