CORD-537 Added public IP gateways for ARP proxy
- Added public IP gateway and MAC pairs to network config for ARP proxy
- Added vSG as a ONOS host
Change-Id: Ia722ba3843297cec7134da5d64bbf188c22762f8
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
index e071550..4672912 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
@@ -16,6 +16,7 @@
package org.onosproject.cordvtn;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -156,7 +157,7 @@
private HostProviderService hostProvider;
private CordVtnRuleInstaller ruleInstaller;
private CordVtnArpProxy arpProxy;
- private volatile MacAddress gatewayMac = MacAddress.NONE;
+ private volatile MacAddress privateGatewayMac = MacAddress.NONE;
/**
* Creates an cordvtn host location provider.
@@ -305,7 +306,7 @@
@Override
public void updateVirtualSubscriberGateways(HostId vSgHostId, String serviceVlan,
- Set<IpAddress> vSgIps) {
+ Map<IpAddress, MacAddress> vSgs) {
Host vSgVm = hostService.getHost(vSgHostId);
if (vSgVm == null || !vSgVm.annotations().value(S_TAG).equals(serviceVlan)) {
@@ -313,8 +314,45 @@
return;
}
- log.info("Updates vSGs in {} with {}", vSgVm.id(), vSgIps.toString());
- ruleInstaller.populateSubscriberGatewayRules(vSgVm, vSgIps);
+ log.info("Updates vSGs in {} with {}", vSgVm.id(), vSgs.toString());
+ vSgs.entrySet().stream()
+ .forEach(entry -> addVirtualSubscriberGateway(
+ vSgVm,
+ entry.getKey(),
+ entry.getValue(),
+ serviceVlan));
+
+ ruleInstaller.populateSubscriberGatewayRules(vSgVm, vSgs.keySet());
+ }
+
+ /**
+ * Adds virtual subscriber gateway to the system.
+ *
+ * @param vSgHost host virtual machine of this vSG
+ * @param vSgIp vSG ip address
+ * @param vSgMac vSG mac address
+ * @param serviceVlan service vlan
+ */
+ public void addVirtualSubscriberGateway(Host vSgHost, IpAddress vSgIp, MacAddress vSgMac, String serviceVlan) {
+ HostId hostId = HostId.hostId(vSgMac);
+ Host host = hostService.getHost(hostId);
+ if (host != null) {
+ log.debug("vSG with {} already exists", vSgMac.toString());
+ return;
+ }
+
+ log.info("vSG with IP({}) MAC({}) detected", vSgIp.toString(), vSgMac.toString());
+ DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
+ .set(S_TAG, serviceVlan);
+
+ HostDescription hostDesc = new DefaultHostDescription(
+ vSgMac,
+ VlanId.NONE,
+ vSgHost.location(),
+ Sets.newHashSet(vSgIp),
+ annotations.build());
+
+ hostProvider.hostDetected(hostId, hostDesc, false);
}
/**
@@ -438,24 +476,24 @@
* Returns public ip addresses of vSGs running inside a give vSG host.
*
* @param vSgHost vSG host
- * @return set of ip address, or empty set
+ * @return map of ip and mac address, or empty map
*/
- private Set<IpAddress> getSubscriberGatewayIps(Host vSgHost) {
+ private Map<IpAddress, MacAddress> getSubscriberGateways(Host vSgHost) {
String vPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID);
String serviceVlan = vSgHost.annotations().value(S_TAG);
OpenstackPort vPort = openstackService.port(vPortId);
if (vPort == null) {
log.warn("Failed to get OpenStack port {} for VM {}", vPortId, vSgHost.id());
- return Sets.newHashSet();
+ return Maps.newHashMap();
}
if (!serviceVlan.equals(getServiceVlan(vPort))) {
log.error("Host({}) s-tag does not match with vPort s-tag", vSgHost.id());
- return Sets.newHashSet();
+ return Maps.newHashMap();
}
- return vPort.allowedAddressPairs().keySet();
+ return vPort.allowedAddressPairs();
}
/**
@@ -485,6 +523,11 @@
*/
private void serviceVmAdded(Host host) {
String vNetId = host.annotations().value(SERVICE_ID);
+ if (vNetId == null) {
+ // ignore this host, it not a VM we injected or a vSG
+ return;
+ }
+
OpenstackNetwork vNet = openstackService.network(vNetId);
if (vNet == null) {
log.warn("Failed to get OpenStack network {} for VM {}({}).",
@@ -509,19 +552,28 @@
} else {
// TODO check if the service needs an update on its group buckets after done CORD-433
ruleInstaller.updateServiceGroup(service);
- arpProxy.addServiceIp(service.serviceIp());
+ arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
// sends gratuitous ARP here for the case of adding existing VMs
// when ONOS or cordvtn app is restarted
- arpProxy.sendGratuitousArp(service.serviceIp(), gatewayMac, Sets.newHashSet(host));
+ arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(host));
}
registerDhcpLease(host, service);
ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), vNet);
- if (host.annotations().value(S_TAG) != null) {
+ String serviceVlan = host.annotations().value(S_TAG);
+ if (serviceVlan != null) {
log.debug("vSG VM detected {}", host.id());
- ruleInstaller.populateSubscriberGatewayRules(host, getSubscriberGatewayIps(host));
+ Map<IpAddress, MacAddress> vSgs = getSubscriberGateways(host);
+ vSgs.entrySet().stream()
+ .forEach(entry -> addVirtualSubscriberGateway(
+ host,
+ entry.getKey(),
+ entry.getValue(),
+ serviceVlan));
+
+ ruleInstaller.populateSubscriberGatewayRules(host, vSgs.keySet());
}
}
@@ -566,7 +618,7 @@
ruleInstaller.updateServiceGroup(service);
if (getHostsWithOpenstackNetwork(vNet).isEmpty()) {
- arpProxy.removeServiceIp(service.serviceIp());
+ arpProxy.removeGateway(service.serviceIp());
}
}
}
@@ -575,14 +627,17 @@
* Sets service network gateway MAC address and sends out gratuitous ARP to all
* VMs to update the gateway MAC address.
*
- * @param mac mac address
+ * @param newMac mac address to update
*/
- private void setServiceGatewayMac(MacAddress mac) {
- if (mac != null && !mac.equals(gatewayMac)) {
- gatewayMac = mac;
- log.debug("Set service gateway MAC address to {}", gatewayMac.toString());
+ private void setPrivateGatewayMac(MacAddress newMac) {
+ if (newMac == null || newMac.equals(privateGatewayMac)) {
+ // no updates, do nothing
+ return;
}
+ privateGatewayMac = newMac;
+ log.debug("Set service gateway MAC address to {}", privateGatewayMac.toString());
+
// TODO get existing service list from XOS and replace the loop below
Set<String> vNets = Sets.newHashSet();
hostService.getHosts().forEach(host -> vNets.add(host.annotations().value(SERVICE_ID)));
@@ -591,15 +646,29 @@
vNets.stream().forEach(vNet -> {
CordService service = getCordService(CordServiceId.of(vNet));
if (service != null) {
- arpProxy.sendGratuitousArp(
- service.serviceIp(),
- gatewayMac,
- service.hosts().keySet());
+ arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
+ arpProxy.sendGratuitousArpForGateway(service.serviceIp(), service.hosts().keySet());
}
});
}
/**
+ * Sets public gateway MAC address.
+ *
+ * @param publicGateways gateway ip and mac address pairs
+ */
+ private void setPublicGatewayMac(Map<IpAddress, MacAddress> publicGateways) {
+ publicGateways.entrySet()
+ .stream()
+ .forEach(entry -> {
+ arpProxy.addGateway(entry.getKey(), entry.getValue());
+ log.debug("Added public gateway IP {}, MAC {}",
+ entry.getKey().toString(), entry.getValue().toString());
+ });
+ // TODO notice gateway MAC change to VMs holds this gateway IP
+ }
+
+ /**
* Updates configurations.
*/
private void readConfiguration() {
@@ -609,7 +678,8 @@
return;
}
- setServiceGatewayMac(config.gatewayMac());
+ setPrivateGatewayMac(config.privateGatewayMac());
+ setPublicGatewayMac(config.publicGateways());
}
private class InternalHostListener implements HostListener {
@@ -644,7 +714,7 @@
return;
}
- arpProxy.processArpPacket(context, ethPacket, gatewayMac);
+ arpProxy.processArpPacket(context, ethPacket);
}
}