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
89 additions
and
50 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 | + |
68 | - | 76 | + IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress()); |
69 | - //Searches the Dst MAC Address based on openstackPortMap | 77 | + MacAddress dstMac = getMacFromHostService(targetIp); |
70 | - MacAddress macAddress = null; | 78 | + if (dstMac == null) { |
71 | - | 79 | + dstMac = getMacFromOpenstack(targetIp); |
72 | - OpenstackPort openstackPort = restHandler.getPorts().stream(). | 80 | + } |
73 | - filter(e -> e.fixedIps().containsValue(Ip4Address.valueOf( | 81 | + |
74 | - dstIPAddress))).findAny().orElse(null); | 82 | + if (dstMac == null) { |
75 | - | 83 | + log.debug("Failed to find MAC address for {}", targetIp.toString()); |
76 | - if (openstackPort != null) { | 84 | + return; |
77 | - macAddress = openstackPort.macAddress(); | 85 | + } |
78 | - log.debug("Found MACAddress: {}", macAddress.toString()); | 86 | + |
79 | - } else { | 87 | + Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(), |
80 | - return; | 88 | + dstMac, |
81 | - } | 89 | + ethRequest); |
82 | - | 90 | + |
83 | - //Creates a response packet | 91 | + TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
84 | - ARP arpReply = new ARP(); | 92 | + .setOutput(pkt.receivedFrom().port()) |
85 | - arpReply.setOpCode(ARP.OP_REPLY) | 93 | + .build(); |
86 | - .setHardwareAddressLength(arp.getHardwareAddressLength()) | 94 | + |
87 | - .setHardwareType(arp.getHardwareType()) | 95 | + packetService.emit(new DefaultOutboundPacket( |
88 | - .setProtocolAddressLength(arp.getProtocolAddressLength()) | 96 | + pkt.receivedFrom().deviceId(), |
89 | - .setProtocolType(arp.getProtocolType()) | 97 | + treatment, |
90 | - .setSenderHardwareAddress(macAddress.toBytes()) | 98 | + ByteBuffer.wrap(ethReply.serialize()))); |
91 | - .setSenderProtocolAddress(dstIPAddress) | 99 | + } |
92 | - .setTargetHardwareAddress(srcMacAddress) | 100 | + |
93 | - .setTargetProtocolAddress(srcIPAddress); | 101 | + /** |
94 | - | 102 | + * Returns MAC address of a host with a given target IP address by asking to |
95 | - //Sends a response packet | 103 | + * OpenStack. It does not support overlapping IP. |
96 | - ethernet.setDestinationMACAddress(srcMacAddress) | 104 | + * |
97 | - .setSourceMACAddress(macAddress) | 105 | + * @param targetIp target ip address |
98 | - .setEtherType(Ethernet.TYPE_ARP) | 106 | + * @return mac address, or null if it fails to fetch the mac |
99 | - .setPayload(arpReply); | 107 | + */ |
100 | - | 108 | + private MacAddress getMacFromOpenstack(IpAddress targetIp) { |
101 | - TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder(); | 109 | + checkNotNull(targetIp); |
102 | - builder.setOutput(pkt.receivedFrom().port()); | 110 | + |
103 | - OutboundPacket packet = new DefaultOutboundPacket(pkt.receivedFrom().deviceId(), | 111 | + OpenstackPort openstackPort = restHandler.getPorts() |
104 | - builder.build(), ByteBuffer.wrap(ethernet.serialize())); | 112 | + .stream() |
105 | - packetService.emit(packet); | 113 | + .filter(port -> port.fixedIps().containsValue(targetIp)) |
114 | + .findFirst() | ||
115 | + .orElse(null); | ||
116 | + | ||
117 | + if (openstackPort != null) { | ||
118 | + log.debug("Found MAC from OpenStack for {}", targetIp.toString()); | ||
119 | + return openstackPort.macAddress(); | ||
120 | + } else { | ||
121 | + return null; | ||
122 | + } | ||
123 | + } | ||
124 | + | ||
125 | + /** | ||
126 | + * Returns MAC address of a host with a given target IP address by asking to | ||
127 | + * host service. It does not support overlapping IP. | ||
128 | + * | ||
129 | + * @param targetIp target ip | ||
130 | + * @return mac address, or null if it fails to find the mac | ||
131 | + */ | ||
132 | + private MacAddress getMacFromHostService(IpAddress targetIp) { | ||
133 | + checkNotNull(targetIp); | ||
134 | + | ||
135 | + Host host = hostService.getHostsByIp(targetIp) | ||
136 | + .stream() | ||
137 | + .findFirst() | ||
138 | + .orElse(null); | ||
139 | + | ||
140 | + if (host != null) { | ||
141 | + log.debug("Found MAC from host service for {}", targetIp.toString()); | ||
142 | + return host.mac(); | ||
143 | + } else { | ||
144 | + return null; | ||
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