Initial support GRE tunnel at SONA

Change-Id: I86536a3ed23d8df45e1dc4033c3068a4dfc9ec73
This commit is contained in:
Jian Li 2018-12-13 15:52:59 +09:00
parent a8549d2d80
commit 2d68c19f1b
16 changed files with 322 additions and 95 deletions

View File

@ -396,6 +396,11 @@ public class OpenstackNetworkManager
.filter(n -> n.getNetworkType() == NetworkType.VXLAN)
.map(IdEntity::getId).collect(Collectors.toSet());
break;
case "GRE" :
networkIds = networks.stream()
.filter(n -> n.getNetworkType() == NetworkType.GRE)
.map(IdEntity::getId).collect(Collectors.toSet());
break;
case "VLAN" :
networkIds = networks.stream()
.filter(n -> n.getNetworkType() == NetworkType.VLAN)

View File

@ -28,6 +28,7 @@ import org.onosproject.cluster.NodeId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@ -87,6 +88,7 @@ import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.g
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.processGarpPacketForFloatingIp;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetId;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
@ -338,17 +340,23 @@ public class OpenstackRoutingFloatingIpHandler {
switch (osNet.getNetworkType()) {
case VXLAN:
if (osNodeService.node(instPort.deviceId()).tunnelPortNum() == null) {
case GRE:
PortNumber portNum = tunnelPortNumByNetId(instPort.networkId(),
osNetworkService, osNodeService.node(instPort.deviceId()));
if (portNum == null) {
log.warn(ERR_FLOW + "no tunnel port");
return;
}
sBuilder.matchTunnelId(Long.parseLong(osNet.getProviderSegID()));
tBuilder.extension(buildExtension(
deviceService,
instPort.deviceId(),
selectedGatewayNode.dataIp().getIp4Address()),
instPort.deviceId())
.setOutput(osNodeService.node(instPort.deviceId()).tunnelPortNum());
.setOutput(portNum);
break;
case VLAN:
if (osNodeService.node(instPort.deviceId()).vlanPortNum() == null) {
@ -389,6 +397,11 @@ public class OpenstackRoutingFloatingIpHandler {
final String error = String.format(errorFormat, floatingIp, cNode.hostname());
throw new IllegalStateException(error);
}
if (osNet.getNetworkType() == NetworkType.GRE && cNode.dataIp() == null) {
final String errorFormat = ERR_FLOW + "GRE mode is not ready for %s";
final String error = String.format(errorFormat, floatingIp, cNode.hostname());
throw new IllegalStateException(error);
}
if (osNet.getNetworkType() == NetworkType.VLAN && cNode.vlanIntf() == null) {
final String errorFormat = ERR_FLOW + "VLAN mode is not ready for %s";
final String error = String.format(errorFormat, floatingIp, cNode.hostname());
@ -421,13 +434,16 @@ public class OpenstackRoutingFloatingIpHandler {
switch (osNet.getNetworkType()) {
case VXLAN:
case GRE:
PortNumber portNum = tunnelPortNumByNetId(instPort.networkId(),
osNetworkService, selectedGatewayNode);
externalTreatmentBuilder.setTunnelId(Long.valueOf(osNet.getProviderSegID()))
.extension(buildExtension(
deviceService,
selectedGatewayNode.intgBridge(),
cNode.dataIp().getIp4Address()),
selectedGatewayNode.intgBridge())
.setOutput(selectedGatewayNode.tunnelPortNum());
.setOutput(portNum);
break;
case VLAN:
externalTreatmentBuilder.pushVlan()
@ -461,6 +477,7 @@ public class OpenstackRoutingFloatingIpHandler {
switch (osNet.getNetworkType()) {
case VXLAN:
case GRE:
sBuilder.matchTunnelId(Long.valueOf(osNet.getProviderSegID()));
break;
case VLAN:

View File

@ -54,7 +54,6 @@ import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
import org.onosproject.openstacknetworking.api.OpenstackRouterService;
import org.onosproject.openstacknetworking.util.RulePopulatorUtil;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackNode.NetworkMode;
import org.onosproject.openstacknode.api.OpenstackNodeEvent;
import org.onosproject.openstacknode.api.OpenstackNodeListener;
import org.onosproject.openstacknode.api.OpenstackNodeService;
@ -98,6 +97,7 @@ import static org.onosproject.openstacknetworking.api.Constants.STAT_OUTBOUND_TA
import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT;
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT_DEFAULT;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetType;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
@ -374,6 +374,7 @@ public class OpenstackRoutingHandler {
Long.parseLong(osNet.getProviderSegID()),
IpPrefix.valueOf(port.ipAddress(), VM_PREFIX),
port.deviceId(),
osNet.getNetworkType(),
install));
setOvsNatIngressRule(gwNode.intgBridge(),
@ -456,6 +457,9 @@ public class OpenstackRoutingHandler {
case VXLAN:
setGatewayIcmpForVxlan(osSubnet, srcNatGw, net, routableSubnets, install);
break;
case GRE:
setGatewayIcmpForGre(osSubnet, srcNatGw, net, routableSubnets, install);
break;
case VLAN:
setGatewayIcmpForVlan(osSubnet, srcNatGw, net, routableSubnets, install);
break;
@ -489,7 +493,24 @@ public class OpenstackRoutingHandler {
network.getProviderSegID(),
osSubnet,
routableSubnets,
NetworkMode.VXLAN,
NetworkType.VXLAN,
install));
}
private void setGatewayIcmpForGre(Subnet osSubnet,
OpenstackNode srcNatGw,
Network network,
Set<Subnet> routableSubnets,
boolean install) {
osNodeService.completeNodes(COMPUTE).stream()
.filter(cNode -> cNode.dataIp() != null)
.forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
cNode,
srcNatGw,
network.getProviderSegID(),
osSubnet,
routableSubnets,
NetworkType.GRE,
install));
}
@ -506,7 +527,7 @@ public class OpenstackRoutingHandler {
network.getProviderSegID(),
osSubnet,
routableSubnets,
NetworkMode.VLAN,
NetworkType.VLAN,
install));
}
@ -598,7 +619,8 @@ public class OpenstackRoutingHandler {
switch (networkType) {
case VXLAN:
setInternalRouterRulesForVxlan(deviceId, srcSegId, dstSegId,
case GRE:
setInternalRouterRulesForTunnel(deviceId, srcSegId, dstSegId,
srcSubnet, dstSubnet, install);
break;
case VLAN:
@ -613,12 +635,12 @@ public class OpenstackRoutingHandler {
}
private void setInternalRouterRulesForVxlan(DeviceId deviceId,
String srcSegmentId,
String dstSegmentId,
IpPrefix srcSubnet,
IpPrefix dstSubnet,
boolean install) {
private void setInternalRouterRulesForTunnel(DeviceId deviceId,
String srcSegmentId,
String dstSegmentId,
IpPrefix srcSubnet,
IpPrefix dstSubnet,
boolean install) {
TrafficSelector selector;
TrafficTreatment treatment;
selector = DefaultTrafficSelector.builder()
@ -734,6 +756,7 @@ public class OpenstackRoutingHandler {
switch (networkType) {
case VXLAN:
case GRE:
sBuilder.matchTunnelId(Long.parseLong(segmentId));
break;
case VLAN:
@ -750,12 +773,14 @@ public class OpenstackRoutingHandler {
switch (networkType) {
case VXLAN:
case GRE:
PortNumber portNum = tunnelPortNumByNetType(networkType.name(), osNode);
tBuilder.extension(buildExtension(
deviceService,
osNode.intgBridge(),
sourceNatGateway.dataIp().getIp4Address()),
osNode.intgBridge())
.setOutput(osNode.tunnelPortNum());
.setOutput(portNum);
break;
case VLAN:
@ -780,6 +805,7 @@ public class OpenstackRoutingHandler {
Long vni,
IpPrefix destVmIp,
DeviceId dstDeviceId,
NetworkType networkType,
boolean install) {
TrafficSelector selector = DefaultTrafficSelector.builder()
@ -787,6 +813,9 @@ public class OpenstackRoutingHandler {
.matchIPDst(destVmIp)
.build();
PortNumber portNum = tunnelPortNumByNetType(networkType.name(),
osNodeService.node(deviceId));
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setTunnelId(vni)
.extension(buildExtension(
@ -794,7 +823,7 @@ public class OpenstackRoutingHandler {
deviceId,
osNodeService.node(dstDeviceId).dataIp().getIp4Address()),
deviceId)
.setOutput(osNodeService.node(deviceId).tunnelPortNum())
.setOutput(portNum)
.build();
osFlowRuleService.setRule(
@ -812,21 +841,21 @@ public class OpenstackRoutingHandler {
String segmentId,
Subnet updatedSubnet,
Set<Subnet> routableSubnets,
NetworkMode networkMode,
NetworkType networkType,
boolean install) {
//At first we install flow rules to gateway with segId and gatewayIp of updated subnet
setRulesToGatewayWithDstIp(osNode, sourceNatGateway, segmentId,
IpAddress.valueOf(updatedSubnet.getGateway()), networkMode, install);
IpAddress.valueOf(updatedSubnet.getGateway()), networkType, install);
routableSubnets.forEach(subnet -> {
setRulesToGatewayWithDstIp(osNode, sourceNatGateway,
segmentId, IpAddress.valueOf(subnet.getGateway()),
networkMode, install);
networkType, install);
Network network = osNetworkAdminService.network(subnet.getNetworkId());
setRulesToGatewayWithDstIp(osNode, sourceNatGateway,
network.getProviderSegID(), IpAddress.valueOf(updatedSubnet.getGateway()),
networkMode, install);
networkType, install);
});
}
@ -834,7 +863,7 @@ public class OpenstackRoutingHandler {
OpenstackNode sourceNatGateway,
String segmentId,
IpAddress dstIp,
NetworkMode networkMode,
NetworkType networkType,
boolean install) {
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
@ -842,17 +871,20 @@ public class OpenstackRoutingHandler {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
switch (networkMode) {
switch (networkType) {
case VXLAN:
case GRE:
sBuilder.matchTunnelId(Long.parseLong(segmentId));
PortNumber portNum = tunnelPortNumByNetType(networkType.name(), osNode);
tBuilder.extension(buildExtension(
deviceService,
osNode.intgBridge(),
sourceNatGateway.dataIp().getIp4Address()),
osNode.intgBridge())
.setOutput(osNode.tunnelPortNum());
.setOutput(portNum);
break;
case VLAN:
sBuilder.matchVlanId(VlanId.vlanId(segmentId));
tBuilder.setOutput(osNode.vlanPortNum());
@ -952,6 +984,7 @@ public class OpenstackRoutingHandler {
switch (networkType) {
case VXLAN:
case GRE:
sBuilder.matchTunnelId(Long.parseLong(segmentId));
break;
case VLAN:
@ -991,6 +1024,7 @@ public class OpenstackRoutingHandler {
switch (networkType) {
case VXLAN:
case GRE:
sBuilder.matchTunnelId(Long.parseLong(segmentId));
break;
case VLAN:
@ -1264,7 +1298,7 @@ public class OpenstackRoutingHandler {
gwNode.intgBridge(),
Long.parseLong(network.getProviderSegID()),
IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
instPort.deviceId(), true));
instPort.deviceId(), network.getNetworkType(), true));
}
}
@ -1280,7 +1314,7 @@ public class OpenstackRoutingHandler {
gwNode.intgBridge(),
Long.parseLong(network.getProviderSegID()),
IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
instPort.deviceId(), false));
instPort.deviceId(), network.getNetworkType(), false));
}
}
}

View File

@ -103,6 +103,7 @@ public class OpenstackRoutingIcmpHandler {
private static final String ERR_DUPLICATE = " already exists";
private static final String VXLAN = "VXLAN";
private static final String GRE = "GRE";
private static final String VLAN = "VLAN";
@Reference(cardinality = ReferenceCardinality.MANDATORY)
@ -517,6 +518,7 @@ public class OpenstackRoutingIcmpHandler {
switch (osNetworkService.networkType(netId)) {
case VXLAN:
case GRE:
tBuilder.setTunnelId(Long.valueOf(segId));
break;
case VLAN:
@ -538,4 +540,5 @@ public class OpenstackRoutingIcmpHandler {
return ((ICMPEcho) icmp.getPayload()).getIdentifier();
}
}
}

View File

@ -27,6 +27,7 @@ import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@ -76,6 +77,7 @@ import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWOR
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SNAT_RULE;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalIpFromSubnet;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalPeerRouterFromSubnet;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetType;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
import static org.slf4j.LoggerFactory.getLogger;
@ -275,6 +277,7 @@ public class OpenstackRoutingSnatHandler {
switch (networkType) {
case VXLAN:
case GRE:
tBuilder.setTunnelId(Long.parseLong(segmentId));
break;
case VLAN:
@ -328,11 +331,13 @@ public class OpenstackRoutingSnatHandler {
DefaultTrafficTreatment.builder(tBuilder.build());
switch (networkType) {
case VXLAN:
case GRE:
PortNumber portNum = tunnelPortNumByNetType(networkType.name(), gNode);
tmpBuilder.extension(RulePopulatorUtil.buildExtension(
deviceService,
gNode.intgBridge(),
srcNode.dataIp().getIp4Address()), gNode.intgBridge())
.setOutput(gNode.tunnelPortNum());
.setOutput(portNum);
break;
case VLAN:
tmpBuilder.setOutput(gNode.vlanPortNum());
@ -364,6 +369,7 @@ public class OpenstackRoutingSnatHandler {
switch (networkType) {
case VXLAN:
case GRE:
sBuilder.matchTunnelId(Long.parseLong(segmentId));
break;
case VLAN:

View File

@ -218,6 +218,7 @@ public class OpenstackSecurityGroupHandler {
private static final IpPrefix IP_PREFIX_ANY = Ip4Prefix.valueOf("0.0.0.0/0");
private static final String VXLAN = "VXLAN";
private static final String GRE = "GRE";
private static final String VLAN = "VLAN";
// We expose pipeline structure to SONA application considering removing pipeline soon.
@ -585,7 +586,7 @@ public class OpenstackSecurityGroupHandler {
if (VLAN.equals(netType)) {
sBuilder.matchVlanId(VlanId.vlanId(segId));
} else if (VXLAN.equals(netType)) {
} else if (VXLAN.equals(netType) || GRE.equals(netType)) {
sBuilder.matchTunnelId(Long.valueOf(segId));
} else {
log.warn("Cannot tag the VID due to lack of support of virtual network type {}", netType);
@ -911,6 +912,7 @@ public class OpenstackSecurityGroupHandler {
switch (netType) {
case VXLAN:
case GRE:
sBuilder.matchTunnelId(Long.valueOf(segId));
break;
case VLAN:

View File

@ -91,6 +91,7 @@ import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.GAT
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.GATEWAY_MAC_DEFAULT;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetId;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
@ -309,7 +310,8 @@ public class OpenstackSwitchingArpHandler {
if (NetworkType.VLAN == network.getNetworkType()) {
sBuilder.matchVlanId(VlanId.vlanId(network.getProviderSegID()));
tBuilder.popVlan();
} else if (NetworkType.VXLAN == network.getNetworkType()) {
} else if (NetworkType.VXLAN == network.getNetworkType() ||
NetworkType.GRE == network.getNetworkType()) {
// do not remove fake gateway ARP rules, if there is another gateway
// which has the same subnet that to be removed
// this only occurs if we have duplicated subnets associated with
@ -373,7 +375,8 @@ public class OpenstackSwitchingArpHandler {
switch (type) {
case VXLAN:
setRemoteArpRequestRuleForVxlan(port, install);
case GRE:
setRemoteArpRequestRuleForTunnel(port, install);
break;
case VLAN:
setArpRequestRuleForVlan(port, install);
@ -396,6 +399,9 @@ public class OpenstackSwitchingArpHandler {
case VXLAN:
setArpReplyRuleForVxlan(port, install);
break;
case GRE:
setArpReplyRuleForGre(port, install);
break;
case VLAN:
setArpReplyRuleForVlan(port, install);
break;
@ -410,7 +416,7 @@ public class OpenstackSwitchingArpHandler {
* @param port instance port
* @param install installation flag
*/
private void setRemoteArpRequestRuleForVxlan(InstancePort port, boolean install) {
private void setRemoteArpRequestRuleForTunnel(InstancePort port, boolean install) {
OpenstackNode localNode = osNodeService.node(port.deviceId());
@ -423,7 +429,7 @@ public class OpenstackSwitchingArpHandler {
.matchTunnelId(Long.valueOf(segId))
.build();
setRemoteArpTreatmentForVxlan(selector, port, localNode, install);
setRemoteArpTreatmentForTunnel(selector, port, localNode, install);
}
/**
@ -469,7 +475,23 @@ public class OpenstackSwitchingArpHandler {
TrafficSelector selector = getArpReplySelectorForVxlan(port);
setLocalArpReplyTreatmentForVxlan(selector, port, install);
setRemoteArpTreatmentForVxlan(selector, port, localNode, install);
setRemoteArpTreatmentForTunnel(selector, port, localNode, install);
}
/**
* Installs flow rules to match ARP reply packets only for GRE.
*
* @param port instance port
* @param install installation flag
*/
private void setArpReplyRuleForGre(InstancePort port, boolean install) {
OpenstackNode localNode = osNodeService.node(port.deviceId());
TrafficSelector selector = getArpReplySelectorForGre(port);
setLocalArpReplyTreatmentForGre(selector, port, install);
setRemoteArpTreatmentForTunnel(selector, port, localNode, install);
}
/**
@ -491,6 +513,11 @@ public class OpenstackSwitchingArpHandler {
return getArpReplySelectorForVnet(port, NetworkType.VXLAN);
}
// a helper method
private TrafficSelector getArpReplySelectorForGre(InstancePort port) {
return getArpReplySelectorForVnet(port, NetworkType.GRE);
}
// a helper method
private TrafficSelector getArpReplySelectorForVlan(InstancePort port) {
return getArpReplySelectorForVnet(port, NetworkType.VLAN);
@ -522,6 +549,13 @@ public class OpenstackSwitchingArpHandler {
setLocalArpReplyTreatmentForVnet(selector, port, NetworkType.VXLAN, install);
}
// a helper method
private void setLocalArpReplyTreatmentForGre(TrafficSelector selector,
InstancePort port,
boolean install) {
setLocalArpReplyTreatmentForVnet(selector, port, NetworkType.GRE, install);
}
// a helper method
private void setLocalArpReplyTreatmentForVlan(TrafficSelector selector,
InstancePort port,
@ -574,20 +608,24 @@ public class OpenstackSwitchingArpHandler {
}
// a helper method
private void setRemoteArpTreatmentForVxlan(TrafficSelector selector,
InstancePort port,
OpenstackNode localNode,
boolean install) {
private void setRemoteArpTreatmentForTunnel(TrafficSelector selector,
InstancePort port,
OpenstackNode localNode,
boolean install) {
for (OpenstackNode remoteNode : osNodeService.completeNodes(COMPUTE)) {
if (!remoteNode.intgBridge().equals(port.deviceId())) {
PortNumber portNum = tunnelPortNumByNetId(port.networkId(),
osNetworkService, remoteNode);
TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
.extension(buildExtension(
deviceService,
remoteNode.intgBridge(),
localNode.dataIp().getIp4Address()),
remoteNode.intgBridge())
.setOutput(remoteNode.tunnelPortNum())
.build();
.extension(buildExtension(
deviceService,
remoteNode.intgBridge(),
localNode.dataIp().getIp4Address()),
remoteNode.intgBridge())
.setOutput(portNum)
.build();
osFlowRuleService.setRule(
appId,

View File

@ -79,6 +79,7 @@ import static org.onosproject.openstacknetworking.api.Constants.VTAG_TABLE;
import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetId;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
import static org.slf4j.LoggerFactory.getLogger;
@ -292,7 +293,7 @@ public class OpenstackSwitchingHandler {
* @param instPort instance port object
* @param install install flag, add the rule if true, remove it otherwise
*/
private void setForwardingRulesForVxlan(InstancePort instPort, boolean install) {
private void setForwardingRulesForTunnel(InstancePort instPort, boolean install) {
// switching rules for the instPorts in the same node
TrafficSelector selector = DefaultTrafficSelector.builder()
// TODO: need to handle IPv6 in near future
@ -326,13 +327,15 @@ public class OpenstackSwitchingHandler {
osNodeService.completeNodes(COMPUTE).stream()
.filter(remoteNode -> !remoteNode.intgBridge().equals(localNode.intgBridge()))
.forEach(remoteNode -> {
PortNumber portNum = tunnelPortNumByNetId(instPort.networkId(),
osNetworkService, remoteNode);
TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
.extension(buildExtension(
deviceService,
remoteNode.intgBridge(),
localNode.dataIp().getIp4Address()),
remoteNode.intgBridge())
.setOutput(remoteNode.tunnelPortNum())
.setOutput(portNum)
.build();
osFlowRuleService.setRule(
@ -408,7 +411,7 @@ public class OpenstackSwitchingHandler {
}
/**
* Configures the flow rule which is for using VXLAN to tag the packet
* Configures the flow rule which is for using VXLAN/GRE to tag the packet
* based on the in_port number of a virtual instance.
* Note that this rule will be inserted in vTag table.
*
@ -493,10 +496,11 @@ public class OpenstackSwitchingHandler {
// TODO: we block a network traffic by referring to segment ID for now
// we might need to find a better way to block the traffic of a network
// in case the segment ID is overlapped in different types network (VXLAN, VLAN)
// in case the segment ID is overlapped in different types network (VXLAN, GRE, VLAN)
switch (type) {
case VXLAN:
setNetworkBlockRulesForVxlan(network.getProviderSegID(), install);
case GRE:
setNetworkBlockRulesForTunnel(network.getProviderSegID(), install);
break;
case VLAN:
setNetworkBlockRulesForVlan(network.getProviderSegID(), install);
@ -509,7 +513,7 @@ public class OpenstackSwitchingHandler {
}
}
private void setNetworkBlockRulesForVxlan(String segmentId, boolean install) {
private void setNetworkBlockRulesForTunnel(String segmentId, boolean install) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchTunnelId(Long.valueOf(segmentId))
.build();
@ -595,7 +599,7 @@ public class OpenstackSwitchingHandler {
* Obtains the VNI from the given instance port.
*
* @param instPort instance port object
* @return VXLAN Network Identifier (VNI)
* @return Virtual Network Identifier (VNI)
*/
private Long getVni(InstancePort instPort) {
Network osNet = osNetworkService.network(instPort.networkId());
@ -730,7 +734,7 @@ public class OpenstackSwitchingHandler {
/**
* Configures L2 forwarding rules.
* Currently, SONA supports Flat, VXLAN and VLAN modes.
* Currently, SONA supports Flat, VXLAN, GRE and VLAN modes.
*
* @param instPort instance port object
* @param install install flag, add the rule if true, remove it otherwise
@ -741,7 +745,8 @@ public class OpenstackSwitchingHandler {
switch (type) {
case VXLAN:
setNetworkRulesForVxlan(instPort, install);
case GRE:
setNetworkRulesForTunnel(instPort, install);
break;
case VLAN:
setNetworkRulesForVlan(instPort, install);
@ -755,9 +760,9 @@ public class OpenstackSwitchingHandler {
}
}
private void setNetworkRulesForVxlan(InstancePort instPort, boolean install) {
private void setNetworkRulesForTunnel(InstancePort instPort, boolean install) {
setTunnelTagIpFlowRules(instPort, install);
setForwardingRulesForVxlan(instPort, install);
setForwardingRulesForTunnel(instPort, install);
if (ARP_BROADCAST_MODE.equals(getArpMode())) {
setTunnelTagArpFlowRules(instPort, install);
@ -790,7 +795,8 @@ public class OpenstackSwitchingHandler {
switch (type) {
case VXLAN:
removeVportRulesForVxlan(instPort);
case GRE:
removeVportRulesForTunnel(instPort);
break;
case VLAN:
removeVportRulesForVlan(instPort);
@ -804,7 +810,7 @@ public class OpenstackSwitchingHandler {
}
}
private void removeVportRulesForVxlan(InstancePort instPort) {
private void removeVportRulesForTunnel(InstancePort instPort) {
setTunnelTagIpFlowRules(instPort, false);
if (ARP_BROADCAST_MODE.equals(getArpMode())) {

View File

@ -50,6 +50,7 @@ import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.cfg.ConfigProperty;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
@ -155,6 +156,7 @@ public final class OpenstackNetworkingUtil {
private static final String ERR_FLOW = "Failed set flows for floating IP %s: ";
private static final String VXLAN = "VXLAN";
private static final String GRE = "GRE";
private static final String VLAN = "VLAN";
private static final String DL_DST = "dl_dst=";
private static final String NW_DST = "nw_dst=";
@ -768,6 +770,7 @@ public final class OpenstackNetworkingUtil {
String modifiedDstIp = dstIp;
if (osNetService.networkType(srcInstancePort.networkId()).equals(VXLAN) ||
osNetService.networkType(srcInstancePort.networkId()).equals(GRE) ||
osNetService.networkType(srcInstancePort.networkId()).equals(VLAN)) {
if (srcIp.equals(dstIp)) {
modifiedDstIp = osNetService.gatewayIp(srcInstancePort.portId());
@ -795,6 +798,7 @@ public final class OpenstackNetworkingUtil {
.append(COMMA);
if (osNetService.networkType(srcInstancePort.networkId()).equals(VXLAN) ||
osNetService.networkType(srcInstancePort.networkId()).equals(GRE) ||
osNetService.networkType(srcInstancePort.networkId()).equals(VLAN)) {
requestStringBuilder.append(TUN_ID)
.append(osNetService.segmentId(srcInstancePort.networkId()))
@ -1045,6 +1049,44 @@ public final class OpenstackNetworkingUtil {
.findAny().get().getIpAddress());
}
/**
* Returns the tunnel port number with specified net ID and openstack node.
*
* @param netId network ID
* @param netService network service
* @param osNode openstack node
* @return tunnel port number
*/
public static PortNumber tunnelPortNumByNetId(String netId,
OpenstackNetworkService netService,
OpenstackNode osNode) {
String netType = netService.networkType(netId);
if (netType == null) {
return null;
}
return tunnelPortNumByNetType(netType, osNode);
}
/**
* Returns the tunnel port number with specified net type and openstack node.
*
* @param netType network type
* @param osNode openstack node
* @return tunnel port number
*/
public static PortNumber tunnelPortNumByNetType(String netType, OpenstackNode osNode) {
switch (netType) {
case VXLAN:
return osNode.vxlanTunnelPortNum();
case GRE:
return osNode.greTunnelPortNum();
default:
return null;
}
}
private static Router getRouterFromSubnet(Subnet subnet,
OpenstackRouterService osRouterService) {
RouterInterface osRouterIface = osRouterService.routerInterfaces().stream()

View File

@ -26,7 +26,8 @@ public final class Constants {
public static final String INTEGRATION_BRIDGE = "br-int";
public static final String TUNNEL_BRIDGE = "br-tun";
public static final String ROUTER_BRIDGE = "br-router";
public static final String DEFAULT_TUNNEL = "vxlan";
public static final String VXLAN_TUNNEL = "vxlan";
public static final String GRE_TUNNEL = "gre";
public static final String PATCH_INTG_BRIDGE = "patch-intg";
public static final String PATCH_ROUT_BRIDGE = "patch-rout";
public static final String GATEWAY = "GATEWAY";

View File

@ -35,7 +35,8 @@ import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
import static org.onosproject.net.AnnotationKeys.PORT_MAC;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
/**
@ -185,15 +186,26 @@ public class DefaultOpenstackNode implements OpenstackNode {
return port != null ? port.number() : null;
}
@Override
public PortNumber tunnelPortNum() {
public PortNumber vxlanTunnelPortNum() {
return tunnelPortNum(VXLAN_TUNNEL);
}
@Override
public PortNumber greTunnelPortNum() {
return tunnelPortNum(GRE_TUNNEL);
}
private PortNumber tunnelPortNum(String tunnelType) {
if (dataIp == null) {
return null;
}
DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
Port port = deviceService.getPorts(intgBridge).stream()
.filter(p -> p.isEnabled() &&
Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
Objects.equals(p.annotations().value(PORT_NAME), tunnelType))
.findAny().orElse(null);
return port != null ? port.number() : null;
}

View File

@ -29,16 +29,6 @@ import java.util.Collection;
*/
public interface OpenstackNode {
/**
* List of valid network modes.
* This includes both physical and virtual network types.
*/
enum NetworkMode {
VXLAN,
VLAN,
FLAT
}
/**
* List of valid node types.
*/
@ -105,11 +95,18 @@ public interface OpenstackNode {
NodeState state();
/**
* Returns the tunnel port number.
* Returns the GRE tunnel port number.
*
* @return port number; null if tunnel port does not exist
* @return GRE port number; null if the GRE tunnel port does not exist
*/
PortNumber tunnelPortNum();
PortNumber greTunnelPortNum();
/**
* Returns the VXLAN tunnel port number.
*
* @return VXLAN port number; null if tunnel port does not exist
*/
PortNumber vxlanTunnelPortNum();
/**
* Returns the vlan port number.

View File

@ -69,7 +69,12 @@ public class OpenstackNodeAdapter implements OpenstackNode {
}
@Override
public PortNumber tunnelPortNum() {
public PortNumber greTunnelPortNum() {
return null;
}
@Override
public PortNumber vxlanTunnelPortNum() {
return null;
}

View File

@ -31,7 +31,8 @@ import org.onosproject.openstacknode.api.OpenstackNodeService;
import org.openstack4j.api.OSClient;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.INTEGRATION_BRIDGE;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.CONTROLLER;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
@ -93,7 +94,8 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand {
deviceService.isAvailable(device.id()),
device.annotations());
if (osNode.dataIp() != null) {
printPortState(deviceService, osNode.intgBridge(), DEFAULT_TUNNEL);
printPortState(deviceService, osNode.intgBridge(), VXLAN_TUNNEL);
printPortState(deviceService, osNode.intgBridge(), GRE_TUNNEL);
}
if (osNode.vlanIntf() != null) {
printPortState(deviceService, osNode.intgBridge(), osNode.vlanIntf());

View File

@ -57,6 +57,7 @@ import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
import org.onosproject.ovsdb.rfc.table.Interface;
import org.openstack4j.api.OSClient;
import org.openstack4j.model.network.NetworkType;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@ -79,7 +80,8 @@ import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.packet.TpPort.tpPort;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.INTEGRATION_BRIDGE;
import static org.onosproject.openstacknode.api.Constants.TUNNEL_BRIDGE;
import static org.onosproject.openstacknode.api.DpdkConfig.DatapathType.NETDEV;
@ -223,8 +225,13 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler {
}
if (osNode.dataIp() != null &&
!isIntfEnabled(osNode, DEFAULT_TUNNEL)) {
createTunnelInterface(osNode);
!isIntfEnabled(osNode, VXLAN_TUNNEL)) {
createVxlanTunnelInterface(osNode);
}
if (osNode.dataIp() != null &&
!isIntfEnabled(osNode, GRE_TUNNEL)) {
createGreTunnelInterface(osNode);
}
if (osNode.dpdkConfig() != null && osNode.dpdkConfig().dpdkIntfs() != null) {
@ -338,13 +345,32 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler {
bridgeConfig.addBridge(builder.build());
}
/**
* Creates a VXLAN tunnel interface in a given openstack node.
*
* @param osNode openstack node
*/
private void createVxlanTunnelInterface(OpenstackNode osNode) {
createTunnelInterface(osNode, NetworkType.VXLAN, VXLAN_TUNNEL);
}
/**
* Creates a GRE tunnel interface in a given openstack node.
*
* @param osNode openstack node
*/
private void createGreTunnelInterface(OpenstackNode osNode) {
createTunnelInterface(osNode, NetworkType.GRE, GRE_TUNNEL);
}
/**
* Creates a tunnel interface in a given openstack node.
*
* @param osNode openstack node
*/
private void createTunnelInterface(OpenstackNode osNode) {
if (isIntfEnabled(osNode, DEFAULT_TUNNEL)) {
private void createTunnelInterface(OpenstackNode osNode,
NetworkType type, String intfName) {
if (isIntfEnabled(osNode, intfName)) {
return;
}
@ -354,16 +380,41 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler {
return;
}
TunnelDescription tunnelDesc = DefaultTunnelDescription.builder()
.deviceId(INTEGRATION_BRIDGE)
.ifaceName(DEFAULT_TUNNEL)
.type(TunnelDescription.Type.VXLAN)
.remote(TunnelEndPoints.flowTunnelEndpoint())
.key(TunnelKeys.flowTunnelKey())
.build();
TunnelDescription tunnelDesc = buildTunnelDesc(type, intfName);
InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
ifaceConfig.addTunnelMode(DEFAULT_TUNNEL, tunnelDesc);
ifaceConfig.addTunnelMode(intfName, tunnelDesc);
}
/**
* Builds tunnel description according to the network type.
*
* @param type network type
* @return tunnel description
*/
private TunnelDescription buildTunnelDesc(NetworkType type, String intfName) {
if (type == NetworkType.VXLAN || type == NetworkType.GRE) {
TunnelDescription.Builder tdBuilder =
DefaultTunnelDescription.builder()
.deviceId(INTEGRATION_BRIDGE)
.ifaceName(intfName)
.remote(TunnelEndPoints.flowTunnelEndpoint())
.key(TunnelKeys.flowTunnelKey());
switch (type) {
case VXLAN:
tdBuilder.type(TunnelDescription.Type.VXLAN);
break;
case GRE:
tdBuilder.type(TunnelDescription.Type.GRE);
break;
default:
return null;
}
return tdBuilder.build();
}
return null;
}
/**
@ -403,7 +454,11 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler {
return initStateDone;
case DEVICE_CREATED:
if (osNode.dataIp() != null &&
!isIntfEnabled(osNode, DEFAULT_TUNNEL)) {
!isIntfEnabled(osNode, VXLAN_TUNNEL)) {
return false;
}
if (osNode.dataIp() != null &&
!isIntfEnabled(osNode, GRE_TUNNEL)) {
return false;
}
if (osNode.vlanIntf() != null &&
@ -761,7 +816,8 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler {
Port port = event.port();
String portName = port.annotations().value(PORT_NAME);
if (osNode.state() == DEVICE_CREATED && (
Objects.equals(portName, DEFAULT_TUNNEL) ||
Objects.equals(portName, VXLAN_TUNNEL) ||
Objects.equals(portName, GRE_TUNNEL) ||
Objects.equals(portName, osNode.vlanIntf()) ||
Objects.equals(portName, osNode.uplinkPort()) ||
containsPhyIntf(osNode, portName)) ||
@ -788,7 +844,8 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler {
Port port = event.port();
String portName = port.annotations().value(PORT_NAME);
if (osNode.state() == COMPLETE && (
Objects.equals(portName, DEFAULT_TUNNEL) ||
Objects.equals(portName, VXLAN_TUNNEL) ||
Objects.equals(portName, GRE_TUNNEL) ||
Objects.equals(portName, osNode.vlanIntf()) ||
Objects.equals(portName, osNode.uplinkPort()) ||
containsPhyIntf(osNode, portName)) ||

View File

@ -99,7 +99,7 @@ import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
import static org.onosproject.net.device.DeviceEvent.Type.PORT_ADDED;
import static org.onosproject.net.device.DeviceEvent.Type.PORT_REMOVED;
import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.INTEGRATION_BRIDGE;
import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
import static org.onosproject.openstacknode.api.Constants.PATCH_ROUT_BRIDGE;
@ -369,7 +369,7 @@ public class DefaultOpenstackNodeHandlerTest {
assertEquals(ERR_STATE_NOT_MATCH, COMPLETE,
testNodeManager.node(COMPUTE_3_HOSTNAME).state());
TEST_DEVICE_SERVICE.removePort(COMPUTE_3_INTG_DEVICE, createPort(
COMPUTE_3_INTG_DEVICE, DEFAULT_TUNNEL));
COMPUTE_3_INTG_DEVICE, VXLAN_TUNNEL));
assertEquals(ERR_STATE_NOT_MATCH, INCOMPLETE,
testNodeManager.node(COMPUTE_3_HOSTNAME).state());
@ -523,7 +523,7 @@ public class DefaultOpenstackNodeHandlerTest {
}
@Override
public PortNumber tunnelPortNum() {
public PortNumber vxlanTunnelPortNum() {
return PortNumber.portNumber(1);
}