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