Committed by
Gerrit Code Review
[ONOS-3952] Implement FloatingIP Handler for OpenstackRoutingService
- Implements floatingIp REST interfaces & event handler - Implements rulePopulate method for floatingIp handler - Fixes minor logics - Changes app structure - exports configuration - Implements case issue. when openstack deletes vm w/o deassociating floatingIp, openstack doesn`t send floatingIp deassociation event. Change-Id: If4d8ac3fecfed1957d84139f94ae31f593a9097b
Showing
6 changed files
with
388 additions
and
98 deletions
... | @@ -80,5 +80,11 @@ public interface OpenstackRoutingService { | ... | @@ -80,5 +80,11 @@ public interface OpenstackRoutingService { |
80 | */ | 80 | */ |
81 | void removeRouterInterface(OpenstackRouterInterface openstackRouterInterface); | 81 | void removeRouterInterface(OpenstackRouterInterface openstackRouterInterface); |
82 | 82 | ||
83 | - | 83 | + /** |
84 | + * Checks floatingIp deassociation when corresponding deleted vm. | ||
85 | + * | ||
86 | + * @param portId Deleted vm | ||
87 | + * @param portInfo | ||
88 | + */ | ||
89 | + void checkDisassociatedFloatingIp(String portId, OpenstackPortInfo portInfo); | ||
84 | } | 90 | } | ... | ... |
... | @@ -15,20 +15,34 @@ | ... | @@ -15,20 +15,34 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.openstacknetworking.routing; | 16 | package org.onosproject.openstacknetworking.routing; |
17 | 17 | ||
18 | - import org.onosproject.event.AbstractEvent; | 18 | +import org.onosproject.openstackinterface.OpenstackFloatingIP; |
19 | +import org.onosproject.openstacknetworking.OpenstackPortInfo; | ||
19 | 20 | ||
20 | /** | 21 | /** |
21 | * Handle FloatingIP Event for Managing Flow Rules In Openstack Nodes. | 22 | * Handle FloatingIP Event for Managing Flow Rules In Openstack Nodes. |
22 | */ | 23 | */ |
23 | public class OpenstackFloatingIPHandler implements Runnable { | 24 | public class OpenstackFloatingIPHandler implements Runnable { |
24 | 25 | ||
25 | - volatile AbstractEvent event; | 26 | + private final OpenstackFloatingIP floatingIP; |
26 | - OpenstackFloatingIPHandler(AbstractEvent event) { | 27 | + private final OpenstackRoutingRulePopulator rulePopulator; |
27 | - this.event = event; | 28 | + private boolean associate; |
29 | + private final OpenstackPortInfo portInfo; | ||
30 | + | ||
31 | + OpenstackFloatingIPHandler(OpenstackRoutingRulePopulator rulePopulator, | ||
32 | + OpenstackFloatingIP openstackFloatingIP, boolean associate, OpenstackPortInfo portInfo) { | ||
33 | + this.floatingIP = openstackFloatingIP; | ||
34 | + this.rulePopulator = rulePopulator; | ||
35 | + this.associate = associate; | ||
36 | + this.portInfo = portInfo; | ||
28 | } | 37 | } |
29 | 38 | ||
30 | @Override | 39 | @Override |
31 | public void run() { | 40 | public void run() { |
41 | + if (associate) { | ||
42 | + rulePopulator.populateFloatingIpRules(floatingIP); | ||
43 | + } else { | ||
44 | + rulePopulator.removeFloatingIpRules(floatingIP, portInfo); | ||
45 | + } | ||
32 | 46 | ||
33 | } | 47 | } |
34 | } | 48 | } | ... | ... |
... | @@ -56,19 +56,18 @@ public class OpenstackPnatHandler implements Runnable { | ... | @@ -56,19 +56,18 @@ public class OpenstackPnatHandler implements Runnable { |
56 | private final int portNum; | 56 | private final int portNum; |
57 | private final OpenstackPort openstackPort; | 57 | private final OpenstackPort openstackPort; |
58 | private final Port port; | 58 | private final Port port; |
59 | + private OpenstackRoutingConfig config; | ||
59 | 60 | ||
60 | private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface"; | 61 | private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface"; |
61 | - // TODO: This will be replaced to get the information from openstacknetworkingservice. | ||
62 | - private static final MacAddress GATEWAYMAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f"); | ||
63 | - private static final MacAddress EXTERNAL_INTERFACE_MAC = MacAddress.valueOf("00:00:00:00:00:11"); | ||
64 | 62 | ||
65 | OpenstackPnatHandler(OpenstackRoutingRulePopulator rulePopulator, PacketContext context, | 63 | OpenstackPnatHandler(OpenstackRoutingRulePopulator rulePopulator, PacketContext context, |
66 | - int portNum, OpenstackPort openstackPort, Port port) { | 64 | + int portNum, OpenstackPort openstackPort, Port port, OpenstackRoutingConfig config) { |
67 | this.rulePopulator = checkNotNull(rulePopulator); | 65 | this.rulePopulator = checkNotNull(rulePopulator); |
68 | this.context = checkNotNull(context); | 66 | this.context = checkNotNull(context); |
69 | this.portNum = checkNotNull(portNum); | 67 | this.portNum = checkNotNull(portNum); |
70 | this.openstackPort = checkNotNull(openstackPort); | 68 | this.openstackPort = checkNotNull(openstackPort); |
71 | this.port = checkNotNull(port); | 69 | this.port = checkNotNull(port); |
70 | + this.config = checkNotNull(config); | ||
72 | } | 71 | } |
73 | 72 | ||
74 | @Override | 73 | @Override |
... | @@ -85,7 +84,8 @@ public class OpenstackPnatHandler implements Runnable { | ... | @@ -85,7 +84,8 @@ public class OpenstackPnatHandler implements Runnable { |
85 | OpenstackRouter router = getOpenstackRouter(openstackPort); | 84 | OpenstackRouter router = getOpenstackRouter(openstackPort); |
86 | 85 | ||
87 | rulePopulator.populatePnatFlowRules(inboundPacket, openstackPort, portNum, | 86 | rulePopulator.populatePnatFlowRules(inboundPacket, openstackPort, portNum, |
88 | - getExternalIp(router), getExternalInterfaceMacAddress(), getExternalRouterMacAddress()); | 87 | + getExternalIp(router), MacAddress.valueOf(config.gatewayExternalInterfaceMac()), |
88 | + MacAddress.valueOf(config.physicalRouterMac())); | ||
89 | 89 | ||
90 | packetOut((Ethernet) ethernet.clone(), inboundPacket.receivedFrom().deviceId(), portNum, router); | 90 | packetOut((Ethernet) ethernet.clone(), inboundPacket.receivedFrom().deviceId(), portNum, router); |
91 | } | 91 | } |
... | @@ -144,8 +144,9 @@ public class OpenstackPnatHandler implements Runnable { | ... | @@ -144,8 +144,9 @@ public class OpenstackPnatHandler implements Runnable { |
144 | iPacket.setSourceAddress(getExternalIp(router).toString()); | 144 | iPacket.setSourceAddress(getExternalIp(router).toString()); |
145 | iPacket.resetChecksum(); | 145 | iPacket.resetChecksum(); |
146 | iPacket.setParent(ethernet); | 146 | iPacket.setParent(ethernet); |
147 | - ethernet.setSourceMACAddress(getExternalInterfaceMacAddress()) | 147 | + ethernet.setPayload(iPacket); |
148 | - .setDestinationMACAddress(getExternalRouterMacAddress()); | 148 | + ethernet.setSourceMACAddress(config.gatewayExternalInterfaceMac()) |
149 | + .setDestinationMACAddress(config.physicalRouterMac()); | ||
149 | ethernet.resetChecksum(); | 150 | ethernet.resetChecksum(); |
150 | 151 | ||
151 | treatment.setOutput(port.number()); | 152 | treatment.setOutput(port.number()); |
... | @@ -153,11 +154,4 @@ public class OpenstackPnatHandler implements Runnable { | ... | @@ -153,11 +154,4 @@ public class OpenstackPnatHandler implements Runnable { |
153 | packetService.emit(new DefaultOutboundPacket(deviceId, treatment.build(), | 154 | packetService.emit(new DefaultOutboundPacket(deviceId, treatment.build(), |
154 | ByteBuffer.wrap(ethernet.serialize()))); | 155 | ByteBuffer.wrap(ethernet.serialize()))); |
155 | } | 156 | } |
156 | - | ||
157 | - private MacAddress getExternalInterfaceMacAddress() { | ||
158 | - return EXTERNAL_INTERFACE_MAC; | ||
159 | - } | ||
160 | - private MacAddress getExternalRouterMacAddress() { | ||
161 | - return GATEWAYMAC; | ||
162 | - } | ||
163 | } | 157 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -16,7 +16,6 @@ | ... | @@ -16,7 +16,6 @@ |
16 | package org.onosproject.openstacknetworking.routing; | 16 | package org.onosproject.openstacknetworking.routing; |
17 | 17 | ||
18 | import com.google.common.collect.Lists; | 18 | import com.google.common.collect.Lists; |
19 | -import com.google.common.collect.Maps; | ||
20 | import org.apache.felix.scr.annotations.Activate; | 19 | import org.apache.felix.scr.annotations.Activate; |
21 | import org.apache.felix.scr.annotations.Component; | 20 | import org.apache.felix.scr.annotations.Component; |
22 | import org.apache.felix.scr.annotations.Deactivate; | 21 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -28,6 +27,7 @@ import org.onlab.packet.IPv4; | ... | @@ -28,6 +27,7 @@ import org.onlab.packet.IPv4; |
28 | import org.onlab.packet.Ip4Address; | 27 | import org.onlab.packet.Ip4Address; |
29 | import org.onlab.packet.MacAddress; | 28 | import org.onlab.packet.MacAddress; |
30 | import org.onlab.packet.UDP; | 29 | import org.onlab.packet.UDP; |
30 | +import org.onlab.util.KryoNamespace; | ||
31 | import org.onosproject.core.ApplicationId; | 31 | import org.onosproject.core.ApplicationId; |
32 | import org.onosproject.core.CoreService; | 32 | import org.onosproject.core.CoreService; |
33 | import org.onosproject.net.DeviceId; | 33 | import org.onosproject.net.DeviceId; |
... | @@ -50,14 +50,18 @@ import org.onosproject.openstackinterface.OpenstackInterfaceService; | ... | @@ -50,14 +50,18 @@ import org.onosproject.openstackinterface.OpenstackInterfaceService; |
50 | import org.onosproject.openstackinterface.OpenstackPort; | 50 | import org.onosproject.openstackinterface.OpenstackPort; |
51 | import org.onosproject.openstackinterface.OpenstackRouter; | 51 | import org.onosproject.openstackinterface.OpenstackRouter; |
52 | import org.onosproject.openstackinterface.OpenstackRouterInterface; | 52 | import org.onosproject.openstackinterface.OpenstackRouterInterface; |
53 | +import org.onosproject.openstacknetworking.OpenstackPortInfo; | ||
53 | import org.onosproject.openstacknetworking.OpenstackRoutingService; | 54 | import org.onosproject.openstacknetworking.OpenstackRoutingService; |
54 | import org.onosproject.openstacknetworking.OpenstackSwitchingService; | 55 | import org.onosproject.openstacknetworking.OpenstackSwitchingService; |
56 | +import org.onosproject.store.serializers.KryoNamespaces; | ||
57 | +import org.onosproject.store.service.ConsistentMap; | ||
58 | +import org.onosproject.store.service.Serializer; | ||
59 | +import org.onosproject.store.service.StorageService; | ||
55 | import org.slf4j.Logger; | 60 | import org.slf4j.Logger; |
56 | import org.slf4j.LoggerFactory; | 61 | import org.slf4j.LoggerFactory; |
57 | 62 | ||
58 | import java.util.Collection; | 63 | import java.util.Collection; |
59 | import java.util.List; | 64 | import java.util.List; |
60 | -import java.util.Map; | ||
61 | import java.util.concurrent.ExecutorService; | 65 | import java.util.concurrent.ExecutorService; |
62 | import java.util.concurrent.Executors; | 66 | import java.util.concurrent.Executors; |
63 | import java.util.stream.Collectors; | 67 | import java.util.stream.Collectors; |
... | @@ -101,14 +105,21 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -101,14 +105,21 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
101 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 105 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
102 | protected NetworkConfigRegistry configRegistry; | 106 | protected NetworkConfigRegistry configRegistry; |
103 | 107 | ||
104 | - | 108 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
109 | + protected StorageService storageService; | ||
105 | 110 | ||
106 | private ApplicationId appId; | 111 | private ApplicationId appId; |
107 | - private Map<String, OpenstackRouterInterface> routerInterfaceMap = Maps.newHashMap(); | 112 | + private ConsistentMap<Integer, String> tpPortNumMap; // Map<PortNum, allocated VM`s Mac & destionation Ip address> |
108 | - private Map<Integer, String> portNumMap = initPortNumMap(); | 113 | + private ConsistentMap<String, OpenstackFloatingIP> floatingIpMap; // Map<FloatingIp`s Id, FloatingIp object> |
109 | private static final String APP_ID = "org.onosproject.openstackrouting"; | 114 | private static final String APP_ID = "org.onosproject.openstackrouting"; |
110 | private static final String PORT_NAME = "portName"; | 115 | private static final String PORT_NAME = "portName"; |
116 | + private static final String PORTNAME_PREFIX_VM = "tap"; | ||
111 | private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface"; | 117 | private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface"; |
118 | + private static final String FLOATING_IP_MAP_NAME = "openstackrouting-floatingip"; | ||
119 | + private static final String TP_PORT_MAP_NAME = "openstackrouting-portnum"; | ||
120 | + private static final int PNAT_PORT_EXPIRE_TIME = 1200 * 1000; | ||
121 | + private static final int TP_PORT_MINIMUM_NUM = 1024; | ||
122 | + private static final int TP_PORT_MAXIMUM_NUM = 65535; | ||
112 | private final ConfigFactory configFactory = | 123 | private final ConfigFactory configFactory = |
113 | new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, OpenstackRoutingConfig.class, "openstackrouting") { | 124 | new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, OpenstackRoutingConfig.class, "openstackrouting") { |
114 | @Override | 125 | @Override |
... | @@ -119,16 +130,19 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -119,16 +130,19 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
119 | private final NetworkConfigListener configListener = new InternalConfigListener(); | 130 | private final NetworkConfigListener configListener = new InternalConfigListener(); |
120 | 131 | ||
121 | private OpenstackRoutingConfig config; | 132 | private OpenstackRoutingConfig config; |
122 | - private static final int PNAT_PORT_NUM_START = 1024; | 133 | + private static final KryoNamespace.Builder FLOATING_IP_SERIALIZER = KryoNamespace.newBuilder() |
123 | - private static final int PNAT_PORT_NUM_END = 65535; | 134 | + .register(KryoNamespaces.API) |
124 | - | 135 | + .register(KryoNamespaces.MISC) |
125 | - private Map<Integer, String> initPortNumMap() { | 136 | + .register(OpenstackFloatingIP.FloatingIpStatus.class) |
126 | - Map<Integer, String> map = Maps.newHashMap(); | 137 | + .register(OpenstackFloatingIP.class) |
127 | - for (int i = PNAT_PORT_NUM_START; i < PNAT_PORT_NUM_END; i++) { | 138 | + .register(Ip4Address.class) |
128 | - map.put(i, ""); | 139 | + .register(String.class); |
129 | - } | 140 | + |
130 | - return map; | 141 | + private static final KryoNamespace.Builder NUMBER_SERIALIZER = KryoNamespace.newBuilder() |
131 | - } | 142 | + .register(KryoNamespaces.API) |
143 | + .register(KryoNamespaces.MISC) | ||
144 | + .register(Integer.class) | ||
145 | + .register(String.class); | ||
132 | 146 | ||
133 | private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor(); | 147 | private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor(); |
134 | private ExecutorService l3EventExecutorService = | 148 | private ExecutorService l3EventExecutorService = |
... | @@ -139,6 +153,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -139,6 +153,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
139 | Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "arp-event")); | 153 | Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "arp-event")); |
140 | private OpenstackIcmpHandler openstackIcmpHandler; | 154 | private OpenstackIcmpHandler openstackIcmpHandler; |
141 | private OpenstackRoutingArpHandler openstackArpHandler; | 155 | private OpenstackRoutingArpHandler openstackArpHandler; |
156 | + private OpenstackRoutingRulePopulator rulePopulator; | ||
142 | 157 | ||
143 | @Activate | 158 | @Activate |
144 | protected void activate() { | 159 | protected void activate() { |
... | @@ -149,6 +164,17 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -149,6 +164,17 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
149 | 164 | ||
150 | readConfiguration(); | 165 | readConfiguration(); |
151 | 166 | ||
167 | + floatingIpMap = storageService.<String, OpenstackFloatingIP>consistentMapBuilder() | ||
168 | + .withSerializer(Serializer.using(FLOATING_IP_SERIALIZER.build())) | ||
169 | + .withName(FLOATING_IP_MAP_NAME) | ||
170 | + .withApplicationId(appId) | ||
171 | + .build(); | ||
172 | + tpPortNumMap = storageService.<Integer, String>consistentMapBuilder() | ||
173 | + .withSerializer(Serializer.using(NUMBER_SERIALIZER.build())) | ||
174 | + .withName(TP_PORT_MAP_NAME) | ||
175 | + .withApplicationId(appId) | ||
176 | + .build(); | ||
177 | + | ||
152 | log.info("onos-openstackrouting started"); | 178 | log.info("onos-openstackrouting started"); |
153 | } | 179 | } |
154 | 180 | ||
... | @@ -159,43 +185,92 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -159,43 +185,92 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
159 | icmpEventExecutorService.shutdown(); | 185 | icmpEventExecutorService.shutdown(); |
160 | arpEventExecutorService.shutdown(); | 186 | arpEventExecutorService.shutdown(); |
161 | 187 | ||
188 | + floatingIpMap.clear(); | ||
189 | + tpPortNumMap.clear(); | ||
190 | + | ||
162 | log.info("onos-openstackrouting stopped"); | 191 | log.info("onos-openstackrouting stopped"); |
163 | } | 192 | } |
164 | 193 | ||
165 | 194 | ||
166 | @Override | 195 | @Override |
167 | public void createFloatingIP(OpenstackFloatingIP openstackFloatingIP) { | 196 | public void createFloatingIP(OpenstackFloatingIP openstackFloatingIP) { |
168 | - | 197 | + floatingIpMap.put(openstackFloatingIP.id(), openstackFloatingIP); |
169 | } | 198 | } |
170 | 199 | ||
171 | @Override | 200 | @Override |
172 | public void updateFloatingIP(OpenstackFloatingIP openstackFloatingIP) { | 201 | public void updateFloatingIP(OpenstackFloatingIP openstackFloatingIP) { |
173 | - | 202 | + if (!floatingIpMap.containsKey(openstackFloatingIP.id())) { |
203 | + log.warn("There`s no information about {} in FloatingIpMap", openstackFloatingIP.id()); | ||
204 | + return; | ||
205 | + } | ||
206 | + if (openstackFloatingIP.portId() == null || openstackFloatingIP.portId().equals("null")) { | ||
207 | + OpenstackFloatingIP floatingIP = floatingIpMap.get(openstackFloatingIP.id()).value(); | ||
208 | + OpenstackPortInfo portInfo = openstackSwitchingService.openstackPortInfo() | ||
209 | + .get(PORTNAME_PREFIX_VM.concat(floatingIP.portId().substring(0, 11))); | ||
210 | + if (portInfo == null) { | ||
211 | + log.warn("There`s no portInfo information about portId {}", floatingIP.portId()); | ||
212 | + return; | ||
213 | + } | ||
214 | + l3EventExecutorService.execute( | ||
215 | + new OpenstackFloatingIPHandler(rulePopulator, floatingIP, false, portInfo)); | ||
216 | + floatingIpMap.replace(floatingIP.id(), openstackFloatingIP); | ||
217 | + } else { | ||
218 | + floatingIpMap.put(openstackFloatingIP.id(), openstackFloatingIP); | ||
219 | + l3EventExecutorService.execute( | ||
220 | + new OpenstackFloatingIPHandler(rulePopulator, openstackFloatingIP, true, null)); | ||
221 | + } | ||
174 | } | 222 | } |
175 | 223 | ||
176 | @Override | 224 | @Override |
177 | public void deleteFloatingIP(String id) { | 225 | public void deleteFloatingIP(String id) { |
178 | - | 226 | + floatingIpMap.remove(id); |
179 | } | 227 | } |
180 | 228 | ||
181 | @Override | 229 | @Override |
182 | public void createRouter(OpenstackRouter openstackRouter) { | 230 | public void createRouter(OpenstackRouter openstackRouter) { |
183 | - checkExternalConnection(openstackRouter, getOpenstackRouterInterface(openstackRouter)); | ||
184 | } | 231 | } |
185 | 232 | ||
186 | @Override | 233 | @Override |
187 | public void updateRouter(OpenstackRouter openstackRouter) { | 234 | public void updateRouter(OpenstackRouter openstackRouter) { |
188 | - checkExternalConnection(openstackRouter, getOpenstackRouterInterface(openstackRouter)); | 235 | + if (openstackRouter.gatewayExternalInfo().externalFixedIps().size() > 0) { |
236 | + Ip4Address externalIp = openstackRouter.gatewayExternalInfo().externalFixedIps() | ||
237 | + .values().stream().findFirst().orElse(null); | ||
238 | + OpenstackRouter router = getRouterfromExternalIp(externalIp); | ||
239 | + checkExternalConnection(router, getOpenstackRouterInterface(router)); | ||
240 | + } else { | ||
241 | + unsetExternalConnection(); | ||
242 | + } | ||
243 | + } | ||
244 | + | ||
245 | + private void unsetExternalConnection() { | ||
246 | + Collection<OpenstackRouter> internalRouters = getExternalRouter(false); | ||
247 | + internalRouters.forEach(r -> | ||
248 | + getOpenstackRouterInterface(r).forEach(i -> rulePopulator.removeExternalRules(i))); | ||
249 | + } | ||
250 | + | ||
251 | + private Collection<OpenstackRouter> getExternalRouter(boolean externalConnection) { | ||
252 | + List<OpenstackRouter> routers; | ||
253 | + if (externalConnection) { | ||
254 | + routers = openstackService.routers() | ||
255 | + .stream() | ||
256 | + .filter(r -> (r.gatewayExternalInfo().externalFixedIps().size() > 0)) | ||
257 | + .collect(Collectors.toList()); | ||
258 | + } else { | ||
259 | + routers = openstackService.routers() | ||
260 | + .stream() | ||
261 | + .filter(r -> (r.gatewayExternalInfo().externalFixedIps().size() == 0)) | ||
262 | + .collect(Collectors.toList()); | ||
263 | + } | ||
264 | + return routers; | ||
189 | } | 265 | } |
190 | 266 | ||
191 | @Override | 267 | @Override |
192 | public void deleteRouter(String id) { | 268 | public void deleteRouter(String id) { |
193 | - //TODO | 269 | + //TODO : In now, there`s nothing to do for deleteRouter process. It is reserved. |
194 | } | 270 | } |
195 | 271 | ||
196 | @Override | 272 | @Override |
197 | public void updateRouterInterface(OpenstackRouterInterface routerInterface) { | 273 | public void updateRouterInterface(OpenstackRouterInterface routerInterface) { |
198 | - routerInterfaceMap.putIfAbsent(routerInterface.id(), routerInterface); | ||
199 | List<OpenstackRouterInterface> routerInterfaces = Lists.newArrayList(); | 274 | List<OpenstackRouterInterface> routerInterfaces = Lists.newArrayList(); |
200 | routerInterfaces.add(routerInterface); | 275 | routerInterfaces.add(routerInterface); |
201 | checkExternalConnection(getOpenstackRouter(routerInterface.id()), routerInterfaces); | 276 | checkExternalConnection(getOpenstackRouter(routerInterface.id()), routerInterfaces); |
... | @@ -203,20 +278,55 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -203,20 +278,55 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
203 | 278 | ||
204 | @Override | 279 | @Override |
205 | public void removeRouterInterface(OpenstackRouterInterface routerInterface) { | 280 | public void removeRouterInterface(OpenstackRouterInterface routerInterface) { |
206 | - OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId, | ||
207 | - openstackService, flowObjectiveService, deviceService, driverService, config); | ||
208 | rulePopulator.removeExternalRules(routerInterface); | 281 | rulePopulator.removeExternalRules(routerInterface); |
209 | - routerInterfaceMap.remove(routerInterface.portId()); | 282 | + } |
283 | + | ||
284 | + @Override | ||
285 | + public void checkDisassociatedFloatingIp(String portId, OpenstackPortInfo portInfo) { | ||
286 | + if (floatingIpMap.size() < 1) { | ||
287 | + log.info("No information in FloatingIpMap"); | ||
288 | + return; | ||
289 | + } | ||
290 | + OpenstackFloatingIP floatingIp = associatedFloatingIps() | ||
291 | + .stream() | ||
292 | + .filter(fIp -> fIp.portId().equals(portId)) | ||
293 | + .findAny() | ||
294 | + .orElse(null); | ||
295 | + if (floatingIp != null && portInfo != null) { | ||
296 | + l3EventExecutorService.execute( | ||
297 | + new OpenstackFloatingIPHandler(rulePopulator, floatingIp, false, portInfo)); | ||
298 | + OpenstackFloatingIP.Builder fBuilder = new OpenstackFloatingIP.Builder() | ||
299 | + .floatingIpAddress(floatingIp.floatingIpAddress()) | ||
300 | + .id(floatingIp.id()) | ||
301 | + .networkId(floatingIp.networkId()) | ||
302 | + .status(floatingIp.status()) | ||
303 | + .tenantId(floatingIp.tenantId()); | ||
304 | + floatingIpMap.replace(floatingIp.id(), fBuilder.build()); | ||
305 | + } else if (portInfo == null) { | ||
306 | + log.warn("portInfo is null as timing issue between ovs port update event and openstack deletePort event"); | ||
307 | + } | ||
308 | + } | ||
309 | + | ||
310 | + private Collection<OpenstackFloatingIP> associatedFloatingIps() { | ||
311 | + List<OpenstackFloatingIP> fIps = Lists.newArrayList(); | ||
312 | + floatingIpMap.values() | ||
313 | + .stream() | ||
314 | + .filter(fIp -> fIp.value().portId() != null) | ||
315 | + .forEach(fIp -> fIps.add(fIp.value())); | ||
316 | + return fIps; | ||
210 | } | 317 | } |
211 | 318 | ||
212 | private void reloadInitL3Rules() { | 319 | private void reloadInitL3Rules() { |
320 | + l3EventExecutorService.submit(() -> | ||
213 | openstackService.ports() | 321 | openstackService.ports() |
214 | .stream() | 322 | .stream() |
215 | .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)) | 323 | .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)) |
216 | .forEach(p -> { | 324 | .forEach(p -> { |
217 | OpenstackRouterInterface routerInterface = portToRouterInterface(p); | 325 | OpenstackRouterInterface routerInterface = portToRouterInterface(p); |
218 | updateRouterInterface(routerInterface); | 326 | updateRouterInterface(routerInterface); |
219 | - }); | 327 | + }) |
328 | + ); | ||
329 | + | ||
220 | } | 330 | } |
221 | 331 | ||
222 | private OpenstackRouterInterface portToRouterInterface(OpenstackPort p) { | 332 | private OpenstackRouterInterface portToRouterInterface(OpenstackPort p) { |
... | @@ -249,8 +359,6 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -249,8 +359,6 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
249 | return; | 359 | return; |
250 | } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) { | 360 | } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) { |
251 | IPv4 iPacket = (IPv4) ethernet.getPayload(); | 361 | IPv4 iPacket = (IPv4) ethernet.getPayload(); |
252 | - OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId, | ||
253 | - openstackService, flowObjectiveService, deviceService, driverService, config); | ||
254 | switch (iPacket.getProtocol()) { | 362 | switch (iPacket.getProtocol()) { |
255 | case IPv4.PROTOCOL_ICMP: | 363 | case IPv4.PROTOCOL_ICMP: |
256 | 364 | ||
... | @@ -275,7 +383,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -275,7 +383,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
275 | OpenstackPort openstackPort = getOpenstackPort(ethernet.getSourceMAC(), | 383 | OpenstackPort openstackPort = getOpenstackPort(ethernet.getSourceMAC(), |
276 | Ip4Address.valueOf(iPacket.getSourceAddress())); | 384 | Ip4Address.valueOf(iPacket.getSourceAddress())); |
277 | l3EventExecutorService.execute(new OpenstackPnatHandler(rulePopulator, context, | 385 | l3EventExecutorService.execute(new OpenstackPnatHandler(rulePopulator, context, |
278 | - portNum, openstackPort, port)); | 386 | + portNum, openstackPort, port, config)); |
279 | break; | 387 | break; |
280 | } | 388 | } |
281 | } else if (ethernet.getEtherType() == Ethernet.TYPE_ARP) { | 389 | } else if (ethernet.getEtherType() == Ethernet.TYPE_ARP) { |
... | @@ -285,11 +393,32 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -285,11 +393,32 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
285 | } | 393 | } |
286 | 394 | ||
287 | private int getPortNum(MacAddress sourceMac, int destinationAddress) { | 395 | private int getPortNum(MacAddress sourceMac, int destinationAddress) { |
288 | - int portNum = portNumMap.keySet().stream() | 396 | + int portNum = findUnusedPortNum(); |
289 | - .filter(k -> portNumMap.get(k).equals("")).findFirst().orElse(0); | 397 | + if (portNum == 0) { |
290 | - portNumMap.replace(portNum, sourceMac.toString().concat(":").concat(String.valueOf(destinationAddress))); | 398 | + clearPortNumMap(); |
399 | + portNum = findUnusedPortNum(); | ||
400 | + } | ||
401 | + tpPortNumMap.put(portNum, sourceMac.toString().concat(":").concat(String.valueOf(destinationAddress))); | ||
291 | return portNum; | 402 | return portNum; |
292 | } | 403 | } |
404 | + | ||
405 | + private int findUnusedPortNum() { | ||
406 | + for (int i = TP_PORT_MINIMUM_NUM; i < TP_PORT_MAXIMUM_NUM; i++) { | ||
407 | + if (!tpPortNumMap.containsKey(i)) { | ||
408 | + return i; | ||
409 | + } | ||
410 | + } | ||
411 | + return 0; | ||
412 | + } | ||
413 | + | ||
414 | + } | ||
415 | + | ||
416 | + private void clearPortNumMap() { | ||
417 | + tpPortNumMap.entrySet().forEach(e -> { | ||
418 | + if (System.currentTimeMillis() - e.getValue().creationTime() > PNAT_PORT_EXPIRE_TIME) { | ||
419 | + tpPortNumMap.remove(e.getKey()); | ||
420 | + } | ||
421 | + }); | ||
293 | } | 422 | } |
294 | 423 | ||
295 | private Port getExternalPort(DeviceId deviceId, String interfaceName) { | 424 | private Port getExternalPort(DeviceId deviceId, String interfaceName) { |
... | @@ -301,29 +430,55 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -301,29 +430,55 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
301 | } | 430 | } |
302 | 431 | ||
303 | private void checkExternalConnection(OpenstackRouter router, | 432 | private void checkExternalConnection(OpenstackRouter router, |
304 | - Collection<OpenstackRouterInterface> routerInterfaces) { | 433 | + Collection<OpenstackRouterInterface> interfaces) { |
305 | checkNotNull(router, "Router can not be null"); | 434 | checkNotNull(router, "Router can not be null"); |
306 | - checkNotNull(routerInterfaces, "routerInterfaces can not be null"); | 435 | + checkNotNull(interfaces, "routerInterfaces can not be null"); |
307 | Ip4Address externalIp = router.gatewayExternalInfo().externalFixedIps() | 436 | Ip4Address externalIp = router.gatewayExternalInfo().externalFixedIps() |
308 | .values().stream().findFirst().orElse(null); | 437 | .values().stream().findFirst().orElse(null); |
309 | if ((externalIp == null) || (!router.gatewayExternalInfo().isEnablePnat())) { | 438 | if ((externalIp == null) || (!router.gatewayExternalInfo().isEnablePnat())) { |
310 | log.debug("Not satisfied to set pnat configuration"); | 439 | log.debug("Not satisfied to set pnat configuration"); |
311 | return; | 440 | return; |
312 | } | 441 | } |
313 | - routerInterfaces.forEach(routerInterface -> initiateL3Rule(router, routerInterface)); | 442 | + if (router.id() == null) { |
443 | + interfaces.forEach(i -> initiateL3Rule(getRouterfromExternalIp(externalIp), i)); | ||
444 | + } else { | ||
445 | + interfaces.forEach(i -> initiateL3Rule(router, i)); | ||
446 | + } | ||
447 | + | ||
448 | + } | ||
449 | + | ||
450 | + private OpenstackRouter getRouterfromExternalIp(Ip4Address externalIp) { | ||
451 | + OpenstackRouter router = getExternalRouter(true) | ||
452 | + .stream() | ||
453 | + .filter(r -> r.gatewayExternalInfo() | ||
454 | + .externalFixedIps() | ||
455 | + .values() | ||
456 | + .stream() | ||
457 | + .findFirst() | ||
458 | + .orElse(null) | ||
459 | + .equals(externalIp)) | ||
460 | + .findAny() | ||
461 | + .orElse(null); | ||
462 | + return checkNotNull(router); | ||
314 | } | 463 | } |
315 | 464 | ||
316 | private void initiateL3Rule(OpenstackRouter router, OpenstackRouterInterface routerInterface) { | 465 | private void initiateL3Rule(OpenstackRouter router, OpenstackRouterInterface routerInterface) { |
317 | long vni = Long.parseLong(openstackService.network(openstackService | 466 | long vni = Long.parseLong(openstackService.network(openstackService |
318 | .port(routerInterface.portId()).networkId()).segmentId()); | 467 | .port(routerInterface.portId()).networkId()).segmentId()); |
319 | - OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId, | ||
320 | - openstackService, flowObjectiveService, deviceService, driverService, config); | ||
321 | rulePopulator.populateExternalRules(vni, router, routerInterface); | 468 | rulePopulator.populateExternalRules(vni, router, routerInterface); |
322 | } | 469 | } |
323 | 470 | ||
324 | private Collection<OpenstackRouterInterface> getOpenstackRouterInterface(OpenstackRouter router) { | 471 | private Collection<OpenstackRouterInterface> getOpenstackRouterInterface(OpenstackRouter router) { |
325 | - return routerInterfaceMap.values().stream().filter(i -> i.id().equals(router.id())) | 472 | + List<OpenstackRouterInterface> interfaces = Lists.newArrayList(); |
326 | - .collect(Collectors.toList()); | 473 | + openstackService.ports() |
474 | + .stream() | ||
475 | + .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)) | ||
476 | + .filter(p -> p.deviceId().equals(router.id())) | ||
477 | + .forEach(p -> { | ||
478 | + OpenstackRouterInterface routerInterface = portToRouterInterface(p); | ||
479 | + interfaces.add(routerInterface); | ||
480 | + }); | ||
481 | + return interfaces; | ||
327 | } | 482 | } |
328 | 483 | ||
329 | private OpenstackRouter getOpenstackRouter(String id) { | 484 | private OpenstackRouter getOpenstackRouter(String id) { |
... | @@ -334,8 +489,8 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -334,8 +489,8 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
334 | private OpenstackPort getOpenstackPort(MacAddress sourceMac, Ip4Address ip4Address) { | 489 | private OpenstackPort getOpenstackPort(MacAddress sourceMac, Ip4Address ip4Address) { |
335 | OpenstackPort openstackPort = openstackService.ports().stream() | 490 | OpenstackPort openstackPort = openstackService.ports().stream() |
336 | .filter(p -> p.macAddress().equals(sourceMac)).findFirst().orElse(null); | 491 | .filter(p -> p.macAddress().equals(sourceMac)).findFirst().orElse(null); |
337 | - return checkNotNull(openstackPort.fixedIps().values().stream().findFirst().orElse(null)) | 492 | + return openstackPort.fixedIps().values().stream().filter(ip -> |
338 | - .equals(ip4Address) ? openstackPort : null; | 493 | + ip.equals(ip4Address)).count() > 0 ? openstackPort : null; |
339 | } | 494 | } |
340 | 495 | ||
341 | private void readConfiguration() { | 496 | private void readConfiguration() { |
... | @@ -353,7 +508,8 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -353,7 +508,8 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
353 | log.debug("Configured info: {}, {}, {}, {}", config.physicalRouterMac(), config.gatewayBridgeId(), | 508 | log.debug("Configured info: {}, {}, {}, {}", config.physicalRouterMac(), config.gatewayBridgeId(), |
354 | config.gatewayExternalInterfaceMac(), config.gatewayExternalInterfaceName()); | 509 | config.gatewayExternalInterfaceMac(), config.gatewayExternalInterfaceName()); |
355 | 510 | ||
356 | - reloadInitL3Rules(); | 511 | + rulePopulator = new OpenstackRoutingRulePopulator(appId, |
512 | + openstackService, flowObjectiveService, deviceService, driverService, config); | ||
357 | 513 | ||
358 | openstackIcmpHandler = new OpenstackIcmpHandler(packetService, deviceService, | 514 | openstackIcmpHandler = new OpenstackIcmpHandler(packetService, deviceService, |
359 | openstackService, config, openstackSwitchingService); | 515 | openstackService, config, openstackSwitchingService); |
... | @@ -361,7 +517,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -361,7 +517,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
361 | 517 | ||
362 | openstackIcmpHandler.requestPacket(appId); | 518 | openstackIcmpHandler.requestPacket(appId); |
363 | openstackArpHandler.requestPacket(appId); | 519 | openstackArpHandler.requestPacket(appId); |
364 | - | 520 | + reloadInitL3Rules(); |
365 | log.info("OpenstackRouting configured"); | 521 | log.info("OpenstackRouting configured"); |
366 | } | 522 | } |
367 | 523 | ||
... | @@ -373,14 +529,12 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { | ... | @@ -373,14 +529,12 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { |
373 | return; | 529 | return; |
374 | } | 530 | } |
375 | 531 | ||
376 | - switch (event.type()) { | 532 | + if (event.type().equals(NetworkConfigEvent.Type.CONFIG_ADDED) || |
377 | - case CONFIG_ADDED: | 533 | + event.type().equals(NetworkConfigEvent.Type.CONFIG_UPDATED)) { |
378 | - case CONFIG_UPDATED: | ||
379 | l3EventExecutorService.execute(OpenstackRoutingManager.this::readConfiguration); | 534 | l3EventExecutorService.execute(OpenstackRoutingManager.this::readConfiguration); |
380 | - break; | 535 | + rulePopulator = new OpenstackRoutingRulePopulator(appId, |
381 | - default: | 536 | + openstackService, flowObjectiveService, deviceService, driverService, config); |
382 | - log.debug("Unsupported event type {}", event.type().toString()); | 537 | + |
383 | - break; | ||
384 | } | 538 | } |
385 | } | 539 | } |
386 | } | 540 | } | ... | ... |
... | @@ -52,6 +52,8 @@ import org.onosproject.openstackinterface.OpenstackPort; | ... | @@ -52,6 +52,8 @@ import org.onosproject.openstackinterface.OpenstackPort; |
52 | import org.onosproject.openstackinterface.OpenstackRouter; | 52 | import org.onosproject.openstackinterface.OpenstackRouter; |
53 | import org.onosproject.openstackinterface.OpenstackRouterInterface; | 53 | import org.onosproject.openstackinterface.OpenstackRouterInterface; |
54 | import org.onosproject.openstackinterface.OpenstackSubnet; | 54 | import org.onosproject.openstackinterface.OpenstackSubnet; |
55 | +import org.onosproject.openstackinterface.OpenstackFloatingIP; | ||
56 | +import org.onosproject.openstacknetworking.OpenstackPortInfo; | ||
55 | import org.slf4j.Logger; | 57 | import org.slf4j.Logger; |
56 | import org.slf4j.LoggerFactory; | 58 | import org.slf4j.LoggerFactory; |
57 | 59 | ||
... | @@ -73,16 +75,17 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -73,16 +75,17 @@ public class OpenstackRoutingRulePopulator { |
73 | private final DriverService driverService; | 75 | private final DriverService driverService; |
74 | private final OpenstackRoutingConfig config; | 76 | private final OpenstackRoutingConfig config; |
75 | 77 | ||
76 | - private static final String PORTNAME_PREFIX_VM = "tap"; | ||
77 | - private static final String PORTNAME_PREFIX_ROUTER = "qr"; | ||
78 | private static final String PORTNAME_PREFIX_TUNNEL = "vxlan"; | 78 | private static final String PORTNAME_PREFIX_TUNNEL = "vxlan"; |
79 | private static final String PORTNAME = "portName"; | 79 | private static final String PORTNAME = "portName"; |
80 | + private static final String PORTNAME_PREFIX_VM = "tap"; | ||
80 | 81 | ||
81 | private static final String PORTNOTNULL = "Port can not be null"; | 82 | private static final String PORTNOTNULL = "Port can not be null"; |
83 | + private static final String DEVICENOTNULL = "Device can not be null"; | ||
82 | private static final String TUNNEL_DESTINATION = "tunnelDst"; | 84 | private static final String TUNNEL_DESTINATION = "tunnelDst"; |
83 | private static final String DEVICE_ANNOTATION_CHANNELID = "channelId"; | 85 | private static final String DEVICE_ANNOTATION_CHANNELID = "channelId"; |
84 | private static final int ROUTING_RULE_PRIORITY = 25000; | 86 | private static final int ROUTING_RULE_PRIORITY = 25000; |
85 | - private static final int PNAT_RULE_PRIORITY = 24000; | 87 | + private static final int FLOATING_RULE_PRIORITY = 42000; |
88 | + private static final int PNAT_RULE_PRIORITY = 26000; | ||
86 | private static final int PNAT_TIMEOUT = 120; | 89 | private static final int PNAT_TIMEOUT = 120; |
87 | private static final MacAddress GATEWAYMAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f"); | 90 | private static final MacAddress GATEWAYMAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f"); |
88 | 91 | ||
... | @@ -134,7 +137,7 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -134,7 +137,7 @@ public class OpenstackRoutingRulePopulator { |
134 | this.externalInterface = externalInterfaceMacAddress; | 137 | this.externalInterface = externalInterfaceMacAddress; |
135 | this.externalRouter = externalRouterMacAddress; | 138 | this.externalRouter = externalRouterMacAddress; |
136 | 139 | ||
137 | - long vni = getVni(openstackPort); | 140 | + long vni = getVni(openstackPort.networkId()); |
138 | 141 | ||
139 | populatePnatIncomingFlowRules(vni, externalIp); | 142 | populatePnatIncomingFlowRules(vni, externalIp); |
140 | populatePnatOutgoingFlowRules(vni, externalIp); | 143 | populatePnatOutgoingFlowRules(vni, externalIp); |
... | @@ -173,7 +176,7 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -173,7 +176,7 @@ public class OpenstackRoutingRulePopulator { |
173 | break; | 176 | break; |
174 | } | 177 | } |
175 | 178 | ||
176 | - Port port = checkNotNull(getPortNumOfExternalInterface(), PORTNOTNULL); | 179 | + Port port = checkNotNull(getPortOfExternalInterface(), PORTNOTNULL); |
177 | tBuilder.setOutput(port.number()); | 180 | tBuilder.setOutput(port.number()); |
178 | 181 | ||
179 | ForwardingObjective fo = DefaultForwardingObjective.builder() | 182 | ForwardingObjective fo = DefaultForwardingObjective.builder() |
... | @@ -188,8 +191,8 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -188,8 +191,8 @@ public class OpenstackRoutingRulePopulator { |
188 | flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo); | 191 | flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo); |
189 | } | 192 | } |
190 | 193 | ||
191 | - private Port getPortNumOfExternalInterface() { | 194 | + private Port getPortOfExternalInterface() { |
192 | - return deviceService.getPorts(inboundPacket.receivedFrom().deviceId()).stream() | 195 | + return deviceService.getPorts(getGatewayNode().id()).stream() |
193 | .filter(p -> p.annotations().value(PORTNAME).equals(config.gatewayExternalInterfaceName())) | 196 | .filter(p -> p.annotations().value(PORTNAME).equals(config.gatewayExternalInterfaceName())) |
194 | .findAny().orElse(null); | 197 | .findAny().orElse(null); |
195 | } | 198 | } |
... | @@ -207,6 +210,7 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -207,6 +210,7 @@ public class OpenstackRoutingRulePopulator { |
207 | 210 | ||
208 | TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | 211 | TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); |
209 | tBuilder.setTunnelId(vni) | 212 | tBuilder.setTunnelId(vni) |
213 | + .setEthDst(inboundPacket.parsed().getSourceMAC()) | ||
210 | .setIpDst(IpAddress.valueOf(iPacket.getSourceAddress())); | 214 | .setIpDst(IpAddress.valueOf(iPacket.getSourceAddress())); |
211 | 215 | ||
212 | switch (iPacket.getProtocol()) { | 216 | switch (iPacket.getProtocol()) { |
... | @@ -226,7 +230,7 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -226,7 +230,7 @@ public class OpenstackRoutingRulePopulator { |
226 | break; | 230 | break; |
227 | } | 231 | } |
228 | 232 | ||
229 | - tBuilder.extension(buildNiciraExtenstion(deviceId, Ip4Address.valueOf(iPacket.getSourceAddress())), deviceId) | 233 | + tBuilder.extension(buildNiciraExtenstion(deviceId, getHostIpfromOpenstackPort(openstackPort)), deviceId) |
230 | .setOutput(getTunnelPort(deviceId)); | 234 | .setOutput(getTunnelPort(deviceId)); |
231 | 235 | ||
232 | ForwardingObjective fo = DefaultForwardingObjective.builder() | 236 | ForwardingObjective fo = DefaultForwardingObjective.builder() |
... | @@ -241,14 +245,37 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -241,14 +245,37 @@ public class OpenstackRoutingRulePopulator { |
241 | flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo); | 245 | flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo); |
242 | } | 246 | } |
243 | 247 | ||
248 | + private Ip4Address getHostIpfromOpenstackPort(OpenstackPort openstackPort) { | ||
249 | + Device device = getDevicefromOpenstackPort(openstackPort); | ||
250 | + return getIPAddressforDevice(device); | ||
251 | + } | ||
252 | + | ||
253 | + private Device getDevicefromOpenstackPort(OpenstackPort openstackPort) { | ||
254 | + String openstackPortName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11); | ||
255 | + Device device = StreamSupport.stream(deviceService.getDevices().spliterator(), false) | ||
256 | + .filter(d -> findPortinDevice(d, openstackPortName)) | ||
257 | + .findAny() | ||
258 | + .orElse(null); | ||
259 | + checkNotNull(device, DEVICENOTNULL); | ||
260 | + return device; | ||
261 | + } | ||
262 | + | ||
263 | + private boolean findPortinDevice(Device d, String openstackPortName) { | ||
264 | + Port port = deviceService.getPorts(d.id()) | ||
265 | + .stream() | ||
266 | + .filter(p -> p.isEnabled() && p.annotations().value(PORTNAME).equals(openstackPortName)) | ||
267 | + .findAny() | ||
268 | + .orElse(null); | ||
269 | + return port != null ? true : false; | ||
270 | + } | ||
271 | + | ||
244 | /** | 272 | /** |
245 | - * Returns NiciraExtension treatment. | 273 | + * Builds NiciraExtension for tagging remoteIp of vxlan. |
246 | * | 274 | * |
247 | - * @param id device id | 275 | + * @param id Device Id of vxlan source device |
248 | - * @param hostIp host ip | 276 | + * @param hostIp Remote Ip of vxlan destination device |
249 | - * @return NiciraExtension treatment | 277 | + * @return NiciraExtension Treatment |
250 | */ | 278 | */ |
251 | - | ||
252 | public ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) { | 279 | public ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) { |
253 | Driver driver = driverService.getDriver(id); | 280 | Driver driver = driverService.getDriver(id); |
254 | DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id)); | 281 | DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id)); |
... | @@ -270,8 +297,8 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -270,8 +297,8 @@ public class OpenstackRoutingRulePopulator { |
270 | /** | 297 | /** |
271 | * Returns port number of vxlan tunnel. | 298 | * Returns port number of vxlan tunnel. |
272 | * | 299 | * |
273 | - * @param deviceId device id | 300 | + * @param deviceId Target Device Id |
274 | - * @return port number of vxlan tunnel | 301 | + * @return PortNumber |
275 | */ | 302 | */ |
276 | public PortNumber getTunnelPort(DeviceId deviceId) { | 303 | public PortNumber getTunnelPort(DeviceId deviceId) { |
277 | Port port = deviceService.getPorts(deviceId).stream() | 304 | Port port = deviceService.getPorts(deviceId).stream() |
... | @@ -328,7 +355,7 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -328,7 +355,7 @@ public class OpenstackRoutingRulePopulator { |
328 | private void populateComputeNodeRules(long vni) { | 355 | private void populateComputeNodeRules(long vni) { |
329 | Device gatewayDevice = getGatewayNode(); | 356 | Device gatewayDevice = getGatewayNode(); |
330 | 357 | ||
331 | - StreamSupport.stream(deviceService.getAvailableDevices().spliterator(), false) | 358 | + StreamSupport.stream(deviceService.getDevices().spliterator(), false) |
332 | .filter(d -> !checkGatewayNode(d.id())) | 359 | .filter(d -> !checkGatewayNode(d.id())) |
333 | .forEach(d -> populateRuleToGateway(d, gatewayDevice, vni)); | 360 | .forEach(d -> populateRuleToGateway(d, gatewayDevice, vni)); |
334 | } | 361 | } |
... | @@ -366,12 +393,8 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -366,12 +393,8 @@ public class OpenstackRoutingRulePopulator { |
366 | return deviceId.toString().equals(config.gatewayBridgeId()); | 393 | return deviceId.toString().equals(config.gatewayBridgeId()); |
367 | } | 394 | } |
368 | 395 | ||
369 | - private long getVni(OpenstackPort openstackPort) { | 396 | + private long getVni(String netId) { |
370 | - return Long.parseLong(openstackService.network(openstackPort.networkId()).segmentId()); | 397 | + return Long.parseLong(openstackService.network(netId).segmentId()); |
371 | - } | ||
372 | - | ||
373 | - private long getVni(OpenstackSubnet openstackSubnet) { | ||
374 | - return Long.parseLong(openstackService.network(openstackSubnet.networkId()).segmentId()); | ||
375 | } | 398 | } |
376 | 399 | ||
377 | /** | 400 | /** |
... | @@ -383,32 +406,122 @@ public class OpenstackRoutingRulePopulator { | ... | @@ -383,32 +406,122 @@ public class OpenstackRoutingRulePopulator { |
383 | OpenstackSubnet openstackSubnet = openstackService.subnet(routerInterface.subnetId()); | 406 | OpenstackSubnet openstackSubnet = openstackService.subnet(routerInterface.subnetId()); |
384 | TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); | 407 | TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); |
385 | sBuilder.matchEthType(Ethernet.TYPE_IPV4) | 408 | sBuilder.matchEthType(Ethernet.TYPE_IPV4) |
386 | - .matchTunnelId(getVni(openstackSubnet)) | 409 | + .matchTunnelId(getVni(openstackSubnet.networkId())) |
387 | .matchEthDst(GATEWAYMAC); | 410 | .matchEthDst(GATEWAYMAC); |
388 | 411 | ||
389 | - StreamSupport.stream(deviceService.getAvailableDevices().spliterator(), false) | 412 | + StreamSupport.stream(deviceService.getDevices().spliterator(), false) |
390 | .forEach(d -> { | 413 | .forEach(d -> { |
391 | if (checkGatewayNode(d.id())) { | 414 | if (checkGatewayNode(d.id())) { |
392 | - removeExternalRule(d.id(), sBuilder, ForwardingObjective.Flag.VERSATILE); | 415 | + removeRule(d.id(), sBuilder, ForwardingObjective.Flag.VERSATILE, ROUTING_RULE_PRIORITY); |
393 | } else { | 416 | } else { |
394 | - removeExternalRule(d.id(), sBuilder, ForwardingObjective.Flag.SPECIFIC); | 417 | + removeRule(d.id(), sBuilder, ForwardingObjective.Flag.SPECIFIC, ROUTING_RULE_PRIORITY); |
395 | } | 418 | } |
396 | }); | 419 | }); |
397 | 420 | ||
398 | } | 421 | } |
399 | 422 | ||
400 | - private void removeExternalRule(DeviceId id, TrafficSelector.Builder sBuilder, ForwardingObjective.Flag flag) { | 423 | + private void removeRule(DeviceId id, TrafficSelector.Builder sBuilder, |
424 | + ForwardingObjective.Flag flag, int priority) { | ||
401 | TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | 425 | TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); |
402 | 426 | ||
403 | ForwardingObjective fo = DefaultForwardingObjective.builder() | 427 | ForwardingObjective fo = DefaultForwardingObjective.builder() |
404 | .withSelector(sBuilder.build()) | 428 | .withSelector(sBuilder.build()) |
405 | .withTreatment(tBuilder.build()) | 429 | .withTreatment(tBuilder.build()) |
406 | .withFlag(flag) | 430 | .withFlag(flag) |
407 | - .withPriority(ROUTING_RULE_PRIORITY) | 431 | + .withPriority(priority) |
408 | .fromApp(appId) | 432 | .fromApp(appId) |
409 | .remove(); | 433 | .remove(); |
410 | 434 | ||
411 | flowObjectiveService.forward(id, fo); | 435 | flowObjectiveService.forward(id, fo); |
412 | } | 436 | } |
413 | 437 | ||
438 | + /** | ||
439 | + * Populates flow rules for floatingIp configuration. | ||
440 | + * | ||
441 | + * @param floatingIP Corresponding floating ip information | ||
442 | + */ | ||
443 | + public void populateFloatingIpRules(OpenstackFloatingIP floatingIP) { | ||
444 | + OpenstackPort port = openstackService.port(floatingIP.portId()); | ||
445 | + //1. incoming rules | ||
446 | + populateFloatingIpIncomingRules(floatingIP, port); | ||
447 | + //2. outgoing rules | ||
448 | + populateFloatingIpOutgoingRules(floatingIP, port); | ||
449 | + } | ||
450 | + | ||
451 | + private void populateFloatingIpIncomingRules(OpenstackFloatingIP floatingIP, OpenstackPort port) { | ||
452 | + DeviceId portDeviceId = getDevicefromOpenstackPort(port).id(); | ||
453 | + Device gatewayNode = getGatewayNode(); | ||
454 | + Device portNode = deviceService.getDevice(portDeviceId); | ||
455 | + | ||
456 | + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); | ||
457 | + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | ||
458 | + | ||
459 | + sBuilder.matchEthType(Ethernet.TYPE_IPV4) | ||
460 | + .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), 32)); | ||
461 | + | ||
462 | + tBuilder.setEthSrc(MacAddress.valueOf(config.gatewayExternalInterfaceMac())) | ||
463 | + .setEthDst(port.macAddress()) | ||
464 | + .setIpDst(floatingIP.fixedIpAddress()) | ||
465 | + .setTunnelId(getVni(port.networkId())) | ||
466 | + .extension(buildNiciraExtenstion(gatewayNode.id(), getIPAddressforDevice(portNode)), gatewayNode.id()) | ||
467 | + .setOutput(getTunnelPort(gatewayNode.id())); | ||
468 | + | ||
469 | + ForwardingObjective fo = DefaultForwardingObjective.builder() | ||
470 | + .withSelector(sBuilder.build()) | ||
471 | + .withTreatment(tBuilder.build()) | ||
472 | + .withFlag(ForwardingObjective.Flag.VERSATILE) | ||
473 | + .withPriority(FLOATING_RULE_PRIORITY) | ||
474 | + .fromApp(appId) | ||
475 | + .add(); | ||
476 | + | ||
477 | + flowObjectiveService.forward(getGatewayNode().id(), fo); | ||
478 | + | ||
479 | + } | ||
480 | + | ||
481 | + private void populateFloatingIpOutgoingRules(OpenstackFloatingIP floatingIP, OpenstackPort port) { | ||
482 | + Port outputPort = checkNotNull(getPortOfExternalInterface(), PORTNOTNULL); | ||
483 | + | ||
484 | + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); | ||
485 | + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | ||
486 | + | ||
487 | + sBuilder.matchEthType(Ethernet.TYPE_IPV4) | ||
488 | + .matchTunnelId(getVni(port.networkId())) | ||
489 | + .matchIPSrc(IpPrefix.valueOf(floatingIP.fixedIpAddress(), 32)); | ||
490 | + | ||
491 | + tBuilder.setIpSrc(floatingIP.floatingIpAddress()) | ||
492 | + .setEthSrc(MacAddress.valueOf(config.gatewayExternalInterfaceMac())) | ||
493 | + .setEthDst(MacAddress.valueOf(config.physicalRouterMac())) | ||
494 | + .setOutput(outputPort.number()); | ||
495 | + | ||
496 | + ForwardingObjective fo = DefaultForwardingObjective.builder() | ||
497 | + .withSelector(sBuilder.build()) | ||
498 | + .withTreatment(tBuilder.build()) | ||
499 | + .withFlag(ForwardingObjective.Flag.VERSATILE) | ||
500 | + .withPriority(FLOATING_RULE_PRIORITY) | ||
501 | + .fromApp(appId) | ||
502 | + .add(); | ||
503 | + | ||
504 | + flowObjectiveService.forward(getGatewayNode().id(), fo); | ||
505 | + } | ||
506 | + | ||
507 | + /** | ||
508 | + * Removes flow rules for floating ip configuration. | ||
509 | + * | ||
510 | + * @param floatingIP Corresponding floating ip information | ||
511 | + */ | ||
512 | + public void removeFloatingIpRules(OpenstackFloatingIP floatingIP, OpenstackPortInfo portInfo) { | ||
513 | + TrafficSelector.Builder sOutgoingBuilder = DefaultTrafficSelector.builder(); | ||
514 | + TrafficSelector.Builder sIncomingBuilder = DefaultTrafficSelector.builder(); | ||
515 | + | ||
516 | + sOutgoingBuilder.matchEthType(Ethernet.TYPE_IPV4) | ||
517 | + .matchTunnelId(portInfo.vni()) | ||
518 | + .matchIPSrc(IpPrefix.valueOf(portInfo.ip(), 32)); | ||
519 | + | ||
520 | + sIncomingBuilder.matchEthType(Ethernet.TYPE_IPV4) | ||
521 | + .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), 32)); | ||
522 | + | ||
523 | + removeRule(getGatewayNode().id(), sOutgoingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY); | ||
524 | + removeRule(getGatewayNode().id(), sIncomingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY); | ||
525 | + } | ||
526 | + | ||
414 | } | 527 | } | ... | ... |
... | @@ -19,6 +19,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ... | @@ -19,6 +19,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; |
19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
20 | import org.onosproject.openstackinterface.OpenstackPort; | 20 | import org.onosproject.openstackinterface.OpenstackPort; |
21 | import org.onosproject.openstackinterface.web.OpenstackPortCodec; | 21 | import org.onosproject.openstackinterface.web.OpenstackPortCodec; |
22 | +import org.onosproject.openstacknetworking.OpenstackPortInfo; | ||
23 | +import org.onosproject.openstacknetworking.OpenstackRoutingService; | ||
22 | import org.onosproject.openstacknetworking.OpenstackSwitchingService; | 24 | import org.onosproject.openstacknetworking.OpenstackSwitchingService; |
23 | import org.onosproject.rest.AbstractWebResource; | 25 | import org.onosproject.rest.AbstractWebResource; |
24 | import org.slf4j.Logger; | 26 | import org.slf4j.Logger; |
... | @@ -42,7 +44,7 @@ import java.io.InputStream; | ... | @@ -42,7 +44,7 @@ import java.io.InputStream; |
42 | public class OpenstackPortWebResource extends AbstractWebResource { | 44 | public class OpenstackPortWebResource extends AbstractWebResource { |
43 | 45 | ||
44 | private final Logger log = LoggerFactory.getLogger(getClass()); | 46 | private final Logger log = LoggerFactory.getLogger(getClass()); |
45 | - | 47 | + private static final String PORTNAME_PREFIX_VM = "tap"; |
46 | private static final OpenstackPortCodec PORT_CODEC = new OpenstackPortCodec(); | 48 | private static final OpenstackPortCodec PORT_CODEC = new OpenstackPortCodec(); |
47 | 49 | ||
48 | @POST | 50 | @POST |
... | @@ -75,7 +77,14 @@ public class OpenstackPortWebResource extends AbstractWebResource { | ... | @@ -75,7 +77,14 @@ public class OpenstackPortWebResource extends AbstractWebResource { |
75 | public Response deletePorts(@PathParam("portUUID") String id) { | 77 | public Response deletePorts(@PathParam("portUUID") String id) { |
76 | OpenstackSwitchingService switchingService = | 78 | OpenstackSwitchingService switchingService = |
77 | getService(OpenstackSwitchingService.class); | 79 | getService(OpenstackSwitchingService.class); |
80 | + OpenstackPortInfo portInfo = switchingService.openstackPortInfo() | ||
81 | + .get(PORTNAME_PREFIX_VM.concat(id.substring(0, 11))); | ||
82 | + OpenstackRoutingService routingService = | ||
83 | + getService(OpenstackRoutingService.class); | ||
84 | + routingService.checkDisassociatedFloatingIp(id, portInfo); | ||
85 | + | ||
78 | switchingService.removePort(id); | 86 | switchingService.removePort(id); |
87 | + | ||
79 | return Response.status(Response.Status.OK).build(); | 88 | return Response.status(Response.Status.OK).build(); |
80 | } | 89 | } |
81 | 90 | ... | ... |
-
Please register or login to post a comment