Committed by
Gerrit Code Review
CORD-537 Added flow rules for vSG connectivity
- Added Q_IN_Q table - Added flow rules for vSG connectivity - Changed to listen port update event from Neutron to update vSG IPs Change-Id: I227ba7a91e90ec0752481ebf623b4e848d585265
Showing
5 changed files
with
146 additions
and
14 deletions
... | @@ -38,7 +38,6 @@ import org.onosproject.net.Host; | ... | @@ -38,7 +38,6 @@ import org.onosproject.net.Host; |
38 | import org.onosproject.net.HostId; | 38 | import org.onosproject.net.HostId; |
39 | import org.onosproject.net.HostLocation; | 39 | import org.onosproject.net.HostLocation; |
40 | import org.onosproject.net.Port; | 40 | import org.onosproject.net.Port; |
41 | -import org.onosproject.net.SparseAnnotations; | ||
42 | import org.onosproject.net.config.ConfigFactory; | 41 | import org.onosproject.net.config.ConfigFactory; |
43 | import org.onosproject.net.config.NetworkConfigEvent; | 42 | import org.onosproject.net.config.NetworkConfigEvent; |
44 | import org.onosproject.net.config.NetworkConfigListener; | 43 | import org.onosproject.net.config.NetworkConfigListener; |
... | @@ -137,10 +136,14 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -137,10 +136,14 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
137 | }; | 136 | }; |
138 | 137 | ||
139 | private static final String DEFAULT_TUNNEL = "vxlan"; | 138 | private static final String DEFAULT_TUNNEL = "vxlan"; |
140 | - private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8"); | ||
141 | private static final String SERVICE_ID = "serviceId"; | 139 | private static final String SERVICE_ID = "serviceId"; |
142 | - private static final String LOCATION_IP = "locationIp"; | ||
143 | private static final String OPENSTACK_VM_ID = "openstackVmId"; | 140 | private static final String OPENSTACK_VM_ID = "openstackVmId"; |
141 | + private static final String OPENSTACK_PORT_ID = "openstackPortId"; | ||
142 | + private static final String DATA_PLANE_IP = "dataPlaneIp"; | ||
143 | + private static final String DATA_PLANE_INTF = "dataPlaneIntf"; | ||
144 | + private static final String S_TAG = "stag"; | ||
145 | + | ||
146 | + private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8"); | ||
144 | 147 | ||
145 | private final ExecutorService eventExecutor = | 148 | private final ExecutorService eventExecutor = |
146 | newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler")); | 149 | newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler")); |
... | @@ -263,18 +266,24 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -263,18 +266,24 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
263 | } | 266 | } |
264 | 267 | ||
265 | Set<IpAddress> ip = Sets.newHashSet(vPort.fixedIps().values()); | 268 | Set<IpAddress> ip = Sets.newHashSet(vPort.fixedIps().values()); |
266 | - SparseAnnotations annotations = DefaultAnnotations.builder() | 269 | + DefaultAnnotations.Builder annotations = DefaultAnnotations.builder() |
267 | - .set(OPENSTACK_VM_ID, vPort.deviceId()) | ||
268 | .set(SERVICE_ID, vPort.networkId()) | 270 | .set(SERVICE_ID, vPort.networkId()) |
269 | - .set(LOCATION_IP, node.dpIp().ip().toString()) | 271 | + .set(OPENSTACK_VM_ID, vPort.deviceId()) |
270 | - .build(); | 272 | + .set(OPENSTACK_PORT_ID, vPort.id()) |
273 | + .set(DATA_PLANE_IP, node.dpIp().ip().toString()) | ||
274 | + .set(DATA_PLANE_INTF, node.dpIntf()); | ||
275 | + | ||
276 | + String serviceVlan = getServiceVlan(vPort); | ||
277 | + if (serviceVlan != null) { | ||
278 | + annotations.set(S_TAG, serviceVlan); | ||
279 | + } | ||
271 | 280 | ||
272 | HostDescription hostDesc = new DefaultHostDescription( | 281 | HostDescription hostDesc = new DefaultHostDescription( |
273 | mac, | 282 | mac, |
274 | VlanId.NONE, | 283 | VlanId.NONE, |
275 | new HostLocation(connectPoint, System.currentTimeMillis()), | 284 | new HostLocation(connectPoint, System.currentTimeMillis()), |
276 | ip, | 285 | ip, |
277 | - annotations); | 286 | + annotations.build()); |
278 | 287 | ||
279 | hostProvider.hostDetected(hostId, hostDesc, false); | 288 | hostProvider.hostDetected(hostId, hostDesc, false); |
280 | } | 289 | } |
... | @@ -294,6 +303,20 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -294,6 +303,20 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
294 | hostProvider.hostVanished(host.id()); | 303 | hostProvider.hostVanished(host.id()); |
295 | } | 304 | } |
296 | 305 | ||
306 | + @Override | ||
307 | + public void updateVirtualSubscriberGateways(HostId vSgHostId, String serviceVlan, | ||
308 | + Set<IpAddress> vSgIps) { | ||
309 | + Host vSgVm = hostService.getHost(vSgHostId); | ||
310 | + | ||
311 | + if (vSgVm == null || !vSgVm.annotations().value(S_TAG).equals(serviceVlan)) { | ||
312 | + log.debug("Invalid vSG updates for {}", serviceVlan); | ||
313 | + return; | ||
314 | + } | ||
315 | + | ||
316 | + log.info("Updates vSGs in {} with {}", vSgVm.id(), vSgIps.toString()); | ||
317 | + ruleInstaller.populateSubscriberGatewayRules(vSgVm, vSgIps); | ||
318 | + } | ||
319 | + | ||
297 | /** | 320 | /** |
298 | * Returns CordService by service ID. | 321 | * Returns CordService by service ID. |
299 | * | 322 | * |
... | @@ -357,10 +380,11 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -357,10 +380,11 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
357 | * Returns IP address for tunneling for a given host. | 380 | * Returns IP address for tunneling for a given host. |
358 | * | 381 | * |
359 | * @param host host | 382 | * @param host host |
360 | - * @return ip address | 383 | + * @return ip address, or null |
361 | */ | 384 | */ |
362 | private IpAddress getTunnelIp(Host host) { | 385 | private IpAddress getTunnelIp(Host host) { |
363 | - return IpAddress.valueOf(host.annotations().value(LOCATION_IP)); | 386 | + String ip = host.annotations().value(DATA_PLANE_IP); |
387 | + return ip == null ? null : IpAddress.valueOf(ip); | ||
364 | } | 388 | } |
365 | 389 | ||
366 | /** | 390 | /** |
... | @@ -374,6 +398,22 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -374,6 +398,22 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
374 | } | 398 | } |
375 | 399 | ||
376 | /** | 400 | /** |
401 | + * Returns s-tag from a given OpenStack port. | ||
402 | + * | ||
403 | + * @param vPort openstack port | ||
404 | + * @return s-tag string | ||
405 | + */ | ||
406 | + private String getServiceVlan(OpenstackPort vPort) { | ||
407 | + checkNotNull(vPort); | ||
408 | + | ||
409 | + if (vPort.name() != null && vPort.name().startsWith(S_TAG)) { | ||
410 | + return vPort.name().split("-")[1]; | ||
411 | + } else { | ||
412 | + return null; | ||
413 | + } | ||
414 | + } | ||
415 | + | ||
416 | + /** | ||
377 | * Returns hosts associated with a given OpenStack network. | 417 | * Returns hosts associated with a given OpenStack network. |
378 | * | 418 | * |
379 | * @param vNet openstack network | 419 | * @param vNet openstack network |
... | @@ -395,6 +435,30 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -395,6 +435,30 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
395 | } | 435 | } |
396 | 436 | ||
397 | /** | 437 | /** |
438 | + * Returns public ip addresses of vSGs running inside a give vSG host. | ||
439 | + * | ||
440 | + * @param vSgHost vSG host | ||
441 | + * @return set of ip address, or empty set | ||
442 | + */ | ||
443 | + private Set<IpAddress> getSubscriberGatewayIps(Host vSgHost) { | ||
444 | + String vPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID); | ||
445 | + String serviceVlan = vSgHost.annotations().value(S_TAG); | ||
446 | + | ||
447 | + OpenstackPort vPort = openstackService.port(vPortId); | ||
448 | + if (vPort == null) { | ||
449 | + log.warn("Failed to get OpenStack port {} for VM {}", vPortId, vSgHost.id()); | ||
450 | + return Sets.newHashSet(); | ||
451 | + } | ||
452 | + | ||
453 | + if (!serviceVlan.equals(getServiceVlan(vPort))) { | ||
454 | + log.error("Host({}) s-tag does not match with vPort s-tag", vSgHost.id()); | ||
455 | + return Sets.newHashSet(); | ||
456 | + } | ||
457 | + | ||
458 | + return vPort.allowedAddressPairs().keySet(); | ||
459 | + } | ||
460 | + | ||
461 | + /** | ||
398 | * Registers static DHCP lease for a given host. | 462 | * Registers static DHCP lease for a given host. |
399 | * | 463 | * |
400 | * @param host host | 464 | * @param host host |
... | @@ -452,8 +516,13 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -452,8 +516,13 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
452 | arpProxy.sendGratuitousArp(service.serviceIp(), gatewayMac, Sets.newHashSet(host)); | 516 | arpProxy.sendGratuitousArp(service.serviceIp(), gatewayMac, Sets.newHashSet(host)); |
453 | } | 517 | } |
454 | 518 | ||
455 | - ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), vNet); | ||
456 | registerDhcpLease(host, service); | 519 | registerDhcpLease(host, service); |
520 | + ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), vNet); | ||
521 | + | ||
522 | + if (host.annotations().value(S_TAG) != null) { | ||
523 | + log.debug("vSG VM detected {}", host.id()); | ||
524 | + ruleInstaller.populateSubscriberGatewayRules(host, getSubscriberGatewayIps(host)); | ||
525 | + } | ||
457 | } | 526 | } |
458 | 527 | ||
459 | /** | 528 | /** |
... | @@ -468,7 +537,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -468,7 +537,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
468 | } | 537 | } |
469 | 538 | ||
470 | String vNetId = host.annotations().value(SERVICE_ID); | 539 | String vNetId = host.annotations().value(SERVICE_ID); |
471 | - OpenstackNetwork vNet = openstackService.network(host.annotations().value(SERVICE_ID)); | 540 | + OpenstackNetwork vNet = openstackService.network(vNetId); |
472 | if (vNet == null) { | 541 | if (vNet == null) { |
473 | log.warn("Failed to get OpenStack network {} for VM {}({}).", | 542 | log.warn("Failed to get OpenStack network {} for VM {}({}).", |
474 | vNetId, | 543 | vNetId, | ... | ... |
This diff is collapsed. Click to expand it.
... | @@ -15,7 +15,11 @@ | ... | @@ -15,7 +15,11 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.cordvtn; | 16 | package org.onosproject.cordvtn; |
17 | 17 | ||
18 | +import org.onlab.packet.IpAddress; | ||
18 | import org.onosproject.net.ConnectPoint; | 19 | import org.onosproject.net.ConnectPoint; |
20 | +import org.onosproject.net.HostId; | ||
21 | + | ||
22 | +import java.util.Set; | ||
19 | 23 | ||
20 | /** | 24 | /** |
21 | * Service for provisioning overlay virtual networks on compute nodes. | 25 | * Service for provisioning overlay virtual networks on compute nodes. |
... | @@ -57,4 +61,14 @@ public interface CordVtnService { | ... | @@ -57,4 +61,14 @@ public interface CordVtnService { |
57 | * @param pServiceId id of the service which provide dependency | 61 | * @param pServiceId id of the service which provide dependency |
58 | */ | 62 | */ |
59 | void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId); | 63 | void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId); |
64 | + | ||
65 | + /** | ||
66 | + * Updates virtual service gateways. | ||
67 | + * | ||
68 | + * @param vSgHost host id of vSG host | ||
69 | + * @param serviceVlan service vlan id | ||
70 | + * @param vSgIps set of ip address of vSGs running in this vSG host | ||
71 | + */ | ||
72 | + void updateVirtualSubscriberGateways(HostId vSgHost, String serviceVlan, | ||
73 | + Set<IpAddress> vSgIps); | ||
60 | } | 74 | } | ... | ... |
... | @@ -220,7 +220,7 @@ public final class RemoteIpCommandUtil { | ... | @@ -220,7 +220,7 @@ public final class RemoteIpCommandUtil { |
220 | return null; | 220 | return null; |
221 | } | 221 | } |
222 | 222 | ||
223 | - log.debug("Execute command {} to {}", command, session.getHost()); | 223 | + log.trace("Execute command {} to {}", command, session.getHost()); |
224 | 224 | ||
225 | try { | 225 | try { |
226 | Channel channel = session.openChannel("exec"); | 226 | Channel channel = session.openChannel("exec"); | ... | ... |
... | @@ -15,6 +15,13 @@ | ... | @@ -15,6 +15,13 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.cordvtn.rest; | 16 | package org.onosproject.cordvtn.rest; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
20 | +import com.google.common.collect.Sets; | ||
21 | +import org.onlab.packet.IpAddress; | ||
22 | +import org.onlab.packet.MacAddress; | ||
23 | +import org.onosproject.cordvtn.CordVtnService; | ||
24 | +import org.onosproject.net.HostId; | ||
18 | import org.onosproject.rest.AbstractWebResource; | 25 | import org.onosproject.rest.AbstractWebResource; |
19 | import org.slf4j.Logger; | 26 | import org.slf4j.Logger; |
20 | import org.slf4j.LoggerFactory; | 27 | import org.slf4j.LoggerFactory; |
... | @@ -29,16 +36,29 @@ import javax.ws.rs.Produces; | ... | @@ -29,16 +36,29 @@ import javax.ws.rs.Produces; |
29 | import javax.ws.rs.core.MediaType; | 36 | import javax.ws.rs.core.MediaType; |
30 | import javax.ws.rs.core.Response; | 37 | import javax.ws.rs.core.Response; |
31 | import java.io.InputStream; | 38 | import java.io.InputStream; |
39 | +import java.util.Set; | ||
40 | + | ||
32 | 41 | ||
33 | /** | 42 | /** |
34 | * Dummy Neutron ML2 mechanism driver. | 43 | * Dummy Neutron ML2 mechanism driver. |
35 | - * It just returns OK for ports resource requests. | 44 | + * It just returns OK for ports resource requests except for the port update. |
36 | */ | 45 | */ |
37 | @Path("ports") | 46 | @Path("ports") |
38 | public class NeutronMl2PortsWebResource extends AbstractWebResource { | 47 | public class NeutronMl2PortsWebResource extends AbstractWebResource { |
39 | protected final Logger log = LoggerFactory.getLogger(getClass()); | 48 | protected final Logger log = LoggerFactory.getLogger(getClass()); |
40 | private static final String PORTS_MESSAGE = "Received ports %s"; | 49 | private static final String PORTS_MESSAGE = "Received ports %s"; |
41 | 50 | ||
51 | + private static final String PORT = "port"; | ||
52 | + private static final String DEVICE_ID = "device_id"; | ||
53 | + private static final String NAME = "name"; | ||
54 | + private static final String MAC_ADDRESS = "mac_address"; | ||
55 | + private static final String ADDRESS_PAIRS = "allowed_address_pairs"; | ||
56 | + private static final String IP_ADDERSS = "ip_address"; | ||
57 | + private static final String STAG_PREFIX = "stag-"; | ||
58 | + private static final int STAG_BEGIN_INDEX = 5; | ||
59 | + | ||
60 | + private final CordVtnService service = get(CordVtnService.class); | ||
61 | + | ||
42 | @POST | 62 | @POST |
43 | @Consumes(MediaType.APPLICATION_JSON) | 63 | @Consumes(MediaType.APPLICATION_JSON) |
44 | @Produces(MediaType.APPLICATION_JSON) | 64 | @Produces(MediaType.APPLICATION_JSON) |
... | @@ -53,6 +73,35 @@ public class NeutronMl2PortsWebResource extends AbstractWebResource { | ... | @@ -53,6 +73,35 @@ public class NeutronMl2PortsWebResource extends AbstractWebResource { |
53 | @Produces(MediaType.APPLICATION_JSON) | 73 | @Produces(MediaType.APPLICATION_JSON) |
54 | public Response updatePorts(@PathParam("id") String id, InputStream input) { | 74 | public Response updatePorts(@PathParam("id") String id, InputStream input) { |
55 | log.debug(String.format(PORTS_MESSAGE, "update")); | 75 | log.debug(String.format(PORTS_MESSAGE, "update")); |
76 | + | ||
77 | + try { | ||
78 | + ObjectMapper mapper = new ObjectMapper(); | ||
79 | + JsonNode jsonNode = mapper.readTree(input).get(PORT); | ||
80 | + log.trace("{}", jsonNode.toString()); | ||
81 | + | ||
82 | + String deviceId = jsonNode.path(DEVICE_ID).asText(); | ||
83 | + String name = jsonNode.path(NAME).asText(); | ||
84 | + if (deviceId.isEmpty() || name.isEmpty() || !name.startsWith(STAG_PREFIX)) { | ||
85 | + // ignore all updates other than allowed address pairs | ||
86 | + return Response.status(Response.Status.OK).build(); | ||
87 | + } | ||
88 | + | ||
89 | + // this is allowed address pairs updates | ||
90 | + MacAddress mac = MacAddress.valueOf(jsonNode.path(MAC_ADDRESS).asText()); | ||
91 | + Set<IpAddress> vSgIps = Sets.newHashSet(); | ||
92 | + jsonNode.path(ADDRESS_PAIRS).forEach(addrPair -> { | ||
93 | + IpAddress ip = IpAddress.valueOf(addrPair.path(IP_ADDERSS).asText()); | ||
94 | + vSgIps.add(ip); | ||
95 | + }); | ||
96 | + | ||
97 | + service.updateVirtualSubscriberGateways( | ||
98 | + HostId.hostId(mac), | ||
99 | + name.substring(STAG_BEGIN_INDEX), | ||
100 | + vSgIps); | ||
101 | + } catch (Exception e) { | ||
102 | + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); | ||
103 | + } | ||
104 | + | ||
56 | return Response.status(Response.Status.OK).build(); | 105 | return Response.status(Response.Status.OK).build(); |
57 | } | 106 | } |
58 | 107 | ... | ... |
-
Please register or login to post a comment