Support NodePort communication model at k8s passthrough mode
Change-Id: I2179ebc9a4812493619c56aa270d8fc4821efbb2
diff --git a/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/Constants.java b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/Constants.java
index d017c50..2c60c79 100644
--- a/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/Constants.java
+++ b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/Constants.java
@@ -39,6 +39,8 @@
public static final String DEFAULT_SERVICE_IP_NAT_MODE_STR = NAT_STATELESS;
public static final String CONTROLLER_MAC_STR = "fe:00:00:00:00:10";
public static final String SERVICE_FAKE_MAC_STR = "fe:00:00:00:00:20";
+ public static final String NODE_FAKE_IP_STR = "172.172.172.172";
+ public static final String NODE_FAKE_MAC_STR = "fe:00:00:00:00:80";
public static final MacAddress DEFAULT_GATEWAY_MAC =
MacAddress.valueOf(DEFAULT_GATEWAY_MAC_STR);
@@ -102,8 +104,6 @@
public static final int PRIORITY_FORCED_ACL_RULE = 50000;
public static final int PRIORITY_ICMP_PROBE_RULE = 50000;
public static final int PRIORITY_NODE_PORT_RULE = 42000;
- public static final int PRIORITY_NODE_PORT_REMOTE_RULE = 41500;
- public static final int PRIORITY_NODE_PORT_INTER_RULE = 40000;
public static final int PRIORITY_DEFAULT_RULE = 0;
// flow table index
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sNodePortHandler.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sNodePortHandler.java
index 0a549cf..c87dfe7 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sNodePortHandler.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sNodePortHandler.java
@@ -67,17 +67,15 @@
import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
import static org.onosproject.k8snetworking.api.Constants.NODE_IP_PREFIX;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_CIDR_RULE;
-import static org.onosproject.k8snetworking.api.Constants.PRIORITY_NODE_PORT_INTER_RULE;
-import static org.onosproject.k8snetworking.api.Constants.PRIORITY_NODE_PORT_REMOTE_RULE;
+import static org.onosproject.k8snetworking.api.Constants.PRIORITY_INTER_ROUTING_RULE;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_NODE_PORT_RULE;
import static org.onosproject.k8snetworking.api.Constants.ROUTING_TABLE;
import static org.onosproject.k8snetworking.api.Constants.SRC;
+import static org.onosproject.k8snetworking.api.Constants.TUN_ENTRY_TABLE;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.getBclassIpPrefixFromCidr;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.getPropertyValue;
-import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.tunnelPortNumByNetId;
-import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.unshiftIpDomain;
-import static org.onosproject.k8snetworking.util.RulePopulatorUtil.buildExtension;
import static org.onosproject.k8snetworking.util.RulePopulatorUtil.buildLoadExtension;
+import static org.onosproject.k8snode.api.K8sApiConfig.Mode.PASSTHROUGH;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -94,8 +92,6 @@
private static final int HOST_CIDR = 32;
private static final String SERVICE_CIDR = "serviceCidr";
private static final String B_CLASS_SUFFIX = "0.0/16";
- private static final String C_CLASS_SUFFIX = ".0/24";
-
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected CoreService coreService;
@@ -167,120 +163,68 @@
String clusterIp = service.getSpec().getClusterIP();
for (ServicePort servicePort : service.getSpec().getPorts()) {
setNodeToServiceRules(k8sNode, clusterIp, servicePort, install);
- setServiceToNodeLocalRules(k8sNode, clusterIp, servicePort, install);
- setServiceToNodeRemoteRules(k8sNode, clusterIp, servicePort, install);
- setExtToIngrRules(k8sNode, servicePort, install);
+ setServiceToNodeRules(k8sNode, clusterIp, servicePort, install);
}
+ }
+ private void setIntgToExtRules(K8sNode k8sNode, String serviceCidr,
+ boolean install) {
+ // for local traffic, we add default flow rules for steering traffic from
+ // integration bridge to external bridge through patch port
+ // for remote traffic, we add default flow rules for steering traffic from
+ // integration bridge to tun bridge through patch port
k8sNodeService.completeNodes().forEach(n -> {
String podCidr = k8sNetworkService.network(n.hostname()).cidr();
String fullCidr = NODE_IP_PREFIX + "." +
podCidr.split("\\.")[2] + "." + B_CLASS_SUFFIX;
- if (n.equals(k8sNode)) {
- setIntgToExtLocalRules(k8sNode, getServiceCidr(), fullCidr, install);
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPSrc(IpPrefix.valueOf(serviceCidr))
+ .matchIPDst(IpPrefix.valueOf(fullCidr));
+
+ PortNumber output;
+ if (n.hostname().equals(k8sNode.hostname())) {
+ output = k8sNode.intgToExtPatchPortNum();
} else {
- setIntgToExtRemoteRules(k8sNode, n, getServiceCidr(), fullCidr, install);
+ output = k8sNode.intgToTunPortNum();
}
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+ .setOutput(output);
+
+ k8sFlowRuleService.setRule(
+ appId,
+ k8sNode.intgBridge(),
+ sBuilder.build(),
+ tBuilder.build(),
+ PRIORITY_CIDR_RULE,
+ ROUTING_TABLE,
+ install);
});
-
- setDefaultExtEgrRule(k8sNode, install);
}
- private void setDefaultExtEgrRule(K8sNode k8sNode, boolean install) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.LOCAL)
- .matchEthType(Ethernet.TYPE_IPV4);
+ private void setTunToIntgRules(K8sNode k8sNode, boolean install) {
+ String podCidr = k8sNetworkService.network(k8sNode.hostname()).cidr();
+ String fullCidr = NODE_IP_PREFIX + "." +
+ podCidr.split("\\.")[2] + "." + B_CLASS_SUFFIX;
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .setOutput(k8sNode.extBridgePortNum());
-
- k8sFlowRuleService.setRule(
- appId,
- k8sNode.extBridge(),
- sBuilder.build(),
- tBuilder.build(),
- PRIORITY_NODE_PORT_INTER_RULE,
- EXT_ENTRY_TABLE,
- install);
- }
-
- private void setIntgToExtLocalRules(K8sNode k8sNode, String serviceCidr,
- String shiftedCidr, boolean install) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
+ TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPSrc(IpPrefix.valueOf(serviceCidr))
- .matchIPDst(IpPrefix.valueOf(shiftedCidr));
+ .matchIPDst(IpPrefix.valueOf(fullCidr))
+ .build();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .setOutput(k8sNode.intgToExtPatchPortNum());
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(k8sNode.tunToIntgPortNum())
+ .build();
k8sFlowRuleService.setRule(
appId,
- k8sNode.intgBridge(),
- sBuilder.build(),
- tBuilder.build(),
- PRIORITY_CIDR_RULE,
- ROUTING_TABLE,
- install);
- }
-
- private void setIntgToExtRemoteRules(K8sNode k8sNodeLocal, K8sNode k8sNodeRemote,
- String serviceCidr, String shiftedCidr,
- boolean install) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPSrc(IpPrefix.valueOf(serviceCidr))
- .matchIPDst(IpPrefix.valueOf(shiftedCidr));
-
- ExtensionTreatment remote = buildExtension(deviceService,
- k8sNodeLocal.intgBridge(), k8sNodeRemote.dataIp().getIp4Address());
-
- PortNumber portNumber = tunnelPortNumByNetId(
- k8sNodeLocal.hostname(), k8sNetworkService, k8sNodeLocal);
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .extension(remote, k8sNodeLocal.intgBridge())
- .setOutput(portNumber);
-
- k8sFlowRuleService.setRule(
- appId,
- k8sNodeLocal.intgBridge(),
- sBuilder.build(),
- tBuilder.build(),
- PRIORITY_CIDR_RULE,
- ROUTING_TABLE,
- install);
- }
-
- private void setExtToIngrRules(K8sNode k8sNode, ServicePort servicePort,
- boolean install) {
- String protocol = servicePort.getProtocol();
- int nodePort = servicePort.getNodePort();
- DeviceId deviceId = k8sNode.extBridge();
-
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(IpPrefix.valueOf(k8sNode.extBridgeIp(), HOST_CIDR));
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.LOCAL);
-
- if (TCP.equals(protocol)) {
- sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP)
- .matchTcpSrc(TpPort.tpPort(nodePort));
- } else if (UDP.equals(protocol)) {
- sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP)
- .matchUdpSrc(TpPort.tpPort(nodePort));
- }
-
- k8sFlowRuleService.setRule(
- appId,
- deviceId,
- sBuilder.build(),
- tBuilder.build(),
- PRIORITY_NODE_PORT_RULE,
- EXT_ENTRY_TABLE,
+ k8sNode.tunBridge(),
+ selector,
+ treatment,
+ PRIORITY_INTER_ROUTING_RULE,
+ TUN_ENTRY_TABLE,
install);
}
@@ -295,7 +239,7 @@
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(IpPrefix.valueOf(k8sNode.extBridgeIp(), HOST_CIDR));
+ .matchIPDst(IpPrefix.valueOf(k8sNode.nodeIp(), HOST_CIDR));
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
.setIpDst(IpAddress.valueOf(clusterIp));
@@ -328,86 +272,30 @@
install);
}
- private void setServiceToNodeLocalRules(K8sNode k8sNode,
- String clusterIp,
- ServicePort servicePort,
- boolean install) {
+ private void setServiceToNodeRules(K8sNode k8sNode,
+ String clusterIp,
+ ServicePort servicePort,
+ boolean install) {
String protocol = servicePort.getProtocol();
int nodePort = servicePort.getNodePort();
int svcPort = servicePort.getPort();
DeviceId deviceId = k8sNode.extBridge();
- String extBridgeIp = k8sNode.extBridgeIp().toString();
- String extBridgePrefix = getBclassIpPrefixFromCidr(extBridgeIp);
+ String nodeIp = k8sNode.nodeIp().toString();
+ String nodeIpPrefix = getBclassIpPrefixFromCidr(nodeIp);
- String podCidr = k8sNetworkService.network(k8sNode.hostname()).cidr();
- String nodePrefix = NODE_IP_PREFIX + "." + podCidr.split("\\.")[2];
-
- if (extBridgePrefix == null) {
+ if (nodeIpPrefix == null) {
return;
}
- String shiftedIp = unshiftIpDomain(extBridgeIp, extBridgePrefix, nodePrefix);
-
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchInPort(k8sNode.extToIntgPatchPortNum())
- .matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(clusterIp), HOST_CIDR))
- .matchIPDst(IpPrefix.valueOf(IpAddress.valueOf(shiftedIp), HOST_CIDR));
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .setIpSrc(k8sNode.extBridgeIp())
- .setEthSrc(k8sNode.extBridgeMac());
-
- if (TCP.equals(protocol)) {
- sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP)
- .matchTcpSrc(TpPort.tpPort(svcPort));
- tBuilder.setTcpSrc(TpPort.tpPort(nodePort));
- } else if (UDP.equals(protocol)) {
- sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP)
- .matchUdpSrc(TpPort.tpPort(svcPort));
- tBuilder.setUdpSrc(TpPort.tpPort(nodePort));
- }
-
- String gatewayIp = k8sNode.extGatewayIp().toString();
- String gatewayPrefix = getBclassIpPrefixFromCidr(gatewayIp);
-
- if (gatewayPrefix == null) {
- return;
- }
-
- ExtensionTreatment loadTreatment = buildLoadExtension(
- deviceService.getDevice(deviceId), B_CLASS, DST, gatewayPrefix);
- tBuilder.extension(loadTreatment, deviceId)
- .setOutput(PortNumber.LOCAL);
-
- k8sFlowRuleService.setRule(
- appId,
- deviceId,
- sBuilder.build(),
- tBuilder.build(),
- PRIORITY_NODE_PORT_RULE,
- EXT_ENTRY_TABLE,
- install);
- }
-
- private void setServiceToNodeRemoteRules(K8sNode k8sNode,
- String clusterIp,
- ServicePort servicePort,
- boolean install) {
- String protocol = servicePort.getProtocol();
- int nodePort = servicePort.getNodePort();
- int svcPort = servicePort.getPort();
- DeviceId deviceId = k8sNode.extBridge();
-
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchInPort(k8sNode.extToIntgPatchPortNum())
.matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(clusterIp), HOST_CIDR));
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .setIpSrc(k8sNode.extBridgeIp())
- .setEthSrc(k8sNode.extBridgeMac());
+ .setIpSrc(k8sNode.nodeIp())
+ .setEthSrc(k8sNode.nodeMac());
if (TCP.equals(protocol)) {
sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP)
@@ -419,24 +307,30 @@
tBuilder.setUdpSrc(TpPort.tpPort(nodePort));
}
- String gatewayIp = k8sNode.extGatewayIp().toString();
- String prefix = getBclassIpPrefixFromCidr(gatewayIp);
-
- if (prefix == null) {
- return;
- }
-
ExtensionTreatment loadTreatment = buildLoadExtension(
- deviceService.getDevice(deviceId), B_CLASS, DST, prefix);
- tBuilder.extension(loadTreatment, deviceId)
- .setOutput(k8sNode.extBridgePortNum());
+ deviceService.getDevice(deviceId), B_CLASS, DST, nodeIpPrefix);
+ tBuilder.extension(loadTreatment, deviceId);
+
+ // in passthrough mode, we steer the traffic to the openstack intg bridge
+ // in normal mode, we steer the traffic to the local port
+ if (k8sNode.mode() == PASSTHROUGH) {
+ PortNumber output = k8sNode.portNumByName(k8sNode.extBridge(),
+ k8sNode.k8sExtToOsPatchPortName());
+ if (output == null) {
+ log.warn("Kubernetes external to OpenStack patch port is null");
+ return;
+ }
+ tBuilder.setOutput(output);
+ } else {
+ tBuilder.setOutput(PortNumber.LOCAL);
+ }
k8sFlowRuleService.setRule(
appId,
deviceId,
sBuilder.build(),
tBuilder.build(),
- PRIORITY_NODE_PORT_REMOTE_RULE,
+ PRIORITY_NODE_PORT_RULE,
EXT_ENTRY_TABLE,
install);
}
@@ -504,6 +398,9 @@
k8sServiceService.services().stream()
.filter(s -> NODE_PORT_TYPE.equals(s.getSpec().getType()))
.forEach(s -> processNodePortEvent(k8sNode, s, true));
+
+ setIntgToExtRules(k8sNode, getServiceCidr(), true);
+ setTunToIntgRules(k8sNode, true);
}
}
}
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sOpenstackIntegrationHandler.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sOpenstackIntegrationHandler.java
index 0c68e20..9e24daa 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sOpenstackIntegrationHandler.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sOpenstackIntegrationHandler.java
@@ -63,6 +63,7 @@
private static final String K8S_NODE_IP = "k8sNodeIp";
private static final String OS_K8S_INT_PORT_NAME = "osK8sIntPortName";
+ private static final String OS_K8S_EXT_PORT_NAME = "osK8sExtPortName";
private static final String POD_CIDR = "podCidr";
private static final String SERVICE_CIDR = "serviceCidr";
private static final String POD_GW_IP = "podGwIp";
@@ -121,7 +122,8 @@
String srcPodPrefix = getBclassIpPrefixFromCidr(nodePodCidr);
String podCidr = srcPodPrefix + B_CLASS_SUFFIX;
String osK8sIntPortName = k8sNode.osToK8sIntgPatchPortName();
- String k8sIntOsPortMac = k8sNode.portMacByName(k8sNode.k8sIntgToOsPatchPortName()).toString();
+ String k8sIntOsPortMac = k8sNode.portMacByName(k8sNode.intgBridge(),
+ k8sNode.k8sIntgToOsPatchPortName()).toString();
String path = install ? "node/pt-install" : "node/pt-uninstall";
@@ -159,6 +161,43 @@
}
}
+ private void setCniPtNodePortRules(K8sNode k8sNode, boolean install) {
+ String k8sNodeIp = k8sNode.nodeIp().toString();
+ String osK8sExtPortName = k8sNode.osToK8sExtPatchPortName();
+
+ String path = install ? "nodeport/pt-install" : "nodeport/pt-uninstall";
+
+ String jsonString = "";
+
+ try {
+ jsonString = new JSONObject()
+ .put(K8S_NODE_IP, k8sNodeIp)
+ .put(SERVICE_CIDR, SERVICE_IP_CIDR_DEFAULT)
+ .put(OS_K8S_EXT_PORT_NAME, osK8sExtPortName)
+ .toString();
+ log.info("push integration configuration {}", jsonString);
+ } catch (JSONException e) {
+ log.error("Failed to generate JSON string");
+ return;
+ }
+
+ HttpAuthenticationFeature feature =
+ HttpAuthenticationFeature.basic(ONOS_USERNAME, ONOS_PASSWORD);
+
+ final Client client = ClientBuilder.newClient();
+ client.register(feature);
+ String host = "http://" + k8sNode.managementIp().toString() + ":" + ONOS_PORT + "/";
+ String endpoint = host + OS_K8S_INTEGRATION_EP;
+ WebTarget wt = client.target(endpoint).path(path);
+ Response response = wt.request(MediaType.APPLICATION_JSON_TYPE)
+ .put(Entity.json(jsonString));
+ final int status = response.getStatus();
+
+ if (status != 200) {
+ log.error("Failed to install/uninstall openstack k8s CNI PT node port rules.");
+ }
+ }
+
private class InternalK8sNodeListener implements K8sNodeListener {
@Override
@@ -190,6 +229,7 @@
}
setCniPtNodeRules(k8sNode, true);
+ setCniPtNodePortRules(k8sNode, true);
}
private void processNodeIncompletion(K8sNode k8sNode) {
@@ -198,6 +238,7 @@
}
setCniPtNodeRules(k8sNode, false);
+ setCniPtNodePortRules(k8sNode, false);
}
}
}
\ No newline at end of file
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sRoutingArpHandler.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sRoutingArpHandler.java
index 93bde9b..1514f6c 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sRoutingArpHandler.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sRoutingArpHandler.java
@@ -178,7 +178,6 @@
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_ARP)
.matchArpOp(ARP.OP_REPLY)
- .matchArpSpa(Ip4Address.valueOf(k8sNode.extGatewayIp().toString()))
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingArpHandler.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingArpHandler.java
index d5c047f..9780435 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingArpHandler.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingArpHandler.java
@@ -15,11 +15,13 @@
*/
package org.onosproject.k8snetworking.impl;
+import org.apache.commons.net.util.SubnetUtils;
import org.onlab.packet.ARP;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
@@ -38,9 +40,10 @@
import org.onosproject.k8snetworking.api.K8sServiceService;
import org.onosproject.k8snode.api.K8sHostService;
import org.onosproject.k8snode.api.K8sNode;
+import org.onosproject.k8snode.api.K8sNodeAdminService;
import org.onosproject.k8snode.api.K8sNodeEvent;
+import org.onosproject.k8snode.api.K8sNodeInfo;
import org.onosproject.k8snode.api.K8sNodeListener;
-import org.onosproject.k8snode.api.K8sNodeService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
@@ -76,11 +79,14 @@
import java.util.stream.Collectors;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import static org.onlab.packet.IpAddress.Version.INET;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.k8snetworking.api.Constants.ARP_BROADCAST_MODE;
import static org.onosproject.k8snetworking.api.Constants.ARP_PROXY_MODE;
import static org.onosproject.k8snetworking.api.Constants.ARP_TABLE;
import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
+import static org.onosproject.k8snetworking.api.Constants.NODE_FAKE_IP_STR;
+import static org.onosproject.k8snetworking.api.Constants.NODE_FAKE_MAC_STR;
import static org.onosproject.k8snetworking.api.Constants.NODE_IP_PREFIX;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_ARP_CONTROL_RULE;
import static org.onosproject.k8snetworking.api.Constants.SERVICE_FAKE_MAC_STR;
@@ -90,6 +96,7 @@
import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.GATEWAY_MAC;
import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.GATEWAY_MAC_DEFAULT;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.allK8sDevices;
+import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.getGatewayIp;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.getPropertyValue;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.unshiftIpDomain;
@@ -139,7 +146,7 @@
protected StorageService storageService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
- protected K8sNodeService k8sNodeService;
+ protected K8sNodeAdminService k8sNodeService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected K8sHostService k8sHostService;
@@ -159,8 +166,6 @@
/** ARP processing mode, broadcast | proxy (default). */
protected String arpMode = ARP_MODE_DEFAULT;
- private MacAddress gwMacAddress;
-
private ConsistentMap<IpAddress, MacAddress> extHostMacStore;
private final ExecutorService eventExecutor = newSingleThreadExecutor(
@@ -305,20 +310,23 @@
String targetIpPrefix = targetIp.toString().split("\\.")[1];
String nodePrefix = NODE_IP_PREFIX + "." + targetIpPrefix;
- String exBridgeCidr = k8sNodeService.completeNodes().stream()
- .map(n -> n.extBridgeIp().toString()).findAny().orElse(null);
+ String origNodeCidr = k8sNodeService.completeNodes().stream()
+ .map(n -> n.nodeIp().toString()).findAny().orElse(null);
- if (exBridgeCidr != null) {
- String extBridgeIp = unshiftIpDomain(targetIp.toString(),
- nodePrefix, exBridgeCidr);
+ if (origNodeCidr != null) {
+ String origNodeIp = unshiftIpDomain(targetIp.toString(),
+ nodePrefix, origNodeCidr);
+ IpPrefix k8sNodeIpCidr = IpPrefix.valueOf(IpAddress.valueOf(origNodeCidr), 24);
+ SubnetUtils k8sNodeSubnet = new SubnetUtils(k8sNodeIpCidr.toString());
+ String k8sNodeGateway = getGatewayIp(k8sNodeIpCidr.toString()).toString();
+ String seekIp = "";
- replyMac = k8sNodeService.completeNodes().stream()
- .filter(n -> extBridgeIp.equals(n.extBridgeIp().toString()))
- .map(K8sNode::extBridgeMac).findAny().orElse(null);
-
- if (replyMac == null) {
- replyMac = extHostMacStore.asJavaMap().get(
- IpAddress.valueOf(extBridgeIp));
+ if (!k8sNodeSubnet.getInfo().isInRange(origNodeIp)) {
+ replyMac = extHostMacStore.asJavaMap().get(IpAddress.valueOf(k8sNodeGateway));
+ seekIp = k8sNodeGateway;
+ } else {
+ replyMac = extHostMacStore.asJavaMap().get(IpAddress.valueOf(origNodeIp));
+ seekIp = origNodeIp;
}
// if the source hosts are not in k8s cluster range,
@@ -328,9 +336,11 @@
K8sNode k8sNode = k8sNodeService.node(cp.deviceId());
if (k8sNode != null) {
- setArpRequest(k8sNode.extBridgeMac().toBytes(),
- k8sNode.extBridgeIp().toOctets(),
- IpAddress.valueOf(extBridgeIp).toOctets(),
+ // we use fake IP and MAC address as a source to
+ // query destination MAC address
+ setArpRequest(MacAddress.valueOf(NODE_FAKE_MAC_STR).toBytes(),
+ IpAddress.valueOf(NODE_FAKE_IP_STR).toOctets(),
+ IpAddress.valueOf(seekIp).toOctets(),
k8sNode);
context.block();
return;
@@ -363,20 +373,34 @@
private void processArpReply(PacketContext context, Ethernet ethPacket) {
ARP arpPacket = (ARP) ethPacket.getPayload();
- ConnectPoint cp = context.inPacket().receivedFrom();
- K8sNode k8sNode = k8sNodeService.node(cp.deviceId());
- if (k8sNode != null &&
- ethPacket.getDestinationMAC().equals(k8sNode.extBridgeMac())) {
- IpAddress srcIp = IpAddress.valueOf(IpAddress.Version.INET,
- arpPacket.getSenderProtocolAddress());
- MacAddress srcMac = MacAddress.valueOf(arpPacket.getSenderHardwareAddress());
+ IpAddress srcIp = IpAddress.valueOf(INET, arpPacket.getSenderProtocolAddress());
+ MacAddress srcMac = MacAddress.valueOf(arpPacket.getSenderHardwareAddress());
+ IpAddress dstIp = IpAddress.valueOf(INET, arpPacket.getTargetProtocolAddress());
+ if (dstIp.equals(IpAddress.valueOf(NODE_FAKE_IP_STR))) {
// we only add the host IP - MAC map store once,
// mutable MAP scenario is not considered for now
if (!extHostMacStore.containsKey(srcIp)) {
extHostMacStore.put(srcIp, srcMac);
}
+
+ K8sNode k8sNode = k8sNodeService.nodes().stream()
+ .filter(n -> n.nodeIp().equals(srcIp))
+ .findAny().orElse(null);
+
+ if (k8sNode == null) {
+ return;
+ } else {
+ if (k8sNode.nodeInfo().nodeMac() != null) {
+ return;
+ }
+ }
+
+ // we update node MAC address which will be referred in node port scenario
+ K8sNodeInfo nodeInfo = new K8sNodeInfo(k8sNode.nodeIp(), srcMac);
+ K8sNode updatedNode = k8sNode.updateNodeInfo(nodeInfo);
+ k8sNodeService.updateNode(updatedNode);
}
}
@@ -385,12 +409,20 @@
Ethernet ethRequest = ARP.buildArpRequest(senderMac,
senderIp, targetIp, VlanId.NO_VID);
+ // TODO: we need to find a way of sending out ARP request to learn
+ // MAC addresses in NORMAL mode
+ PortNumber k8sExtToOsPatchPort = k8sNode.portNumByName(k8sNode.extBridge(),
+ k8sNode.k8sExtToOsPatchPortName());
+ if (k8sExtToOsPatchPort == null) {
+ log.warn("Kubernetes external to OpenStack patch port is null");
+ return;
+ }
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(k8sNode.intgToExtPatchPortNum())
+ .setOutput(k8sExtToOsPatchPort)
.build();
packetService.emit(new DefaultOutboundPacket(
- k8sNode.intgBridge(),
+ k8sNode.extBridge(),
treatment,
ByteBuffer.wrap(ethRequest.serialize())));
}
@@ -466,6 +498,7 @@
}
setDefaultArpRule(node, true);
+ learnK8sNodeMac(node);
}
private void processNodeIncompletion(K8sNode node) {
@@ -516,5 +549,17 @@
install
);
}
+
+ private void learnK8sNodeMac(K8sNode k8sNode) {
+ // if we already have a learned MAC address, we skip learning process
+ if (k8sNode.nodeMac() != null) {
+ return;
+ }
+
+ setArpRequest(MacAddress.valueOf(NODE_FAKE_MAC_STR).toBytes(),
+ IpAddress.valueOf(NODE_FAKE_IP_STR).toOctets(),
+ k8sNode.nodeIp().toOctets(),
+ k8sNode);
+ }
}
}
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingGatewayHandler.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingGatewayHandler.java
index 8083e88..2c580cb 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingGatewayHandler.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingGatewayHandler.java
@@ -64,6 +64,7 @@
import static org.onosproject.k8snetworking.api.Constants.HOST_PREFIX;
import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
import static org.onosproject.k8snetworking.api.Constants.LOCAL_ENTRY_TABLE;
+import static org.onosproject.k8snetworking.api.Constants.NODE_IP_PREFIX;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_ARP_REPLY_RULE;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_GATEWAY_RULE;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_INTER_NODE_RULE;
@@ -283,6 +284,23 @@
PRIORITY_INTER_NODE_RULE,
TUN_ENTRY_TABLE,
install);
+
+ String nodeIpPrefix = NODE_IP_PREFIX + ".0.0.0/8";
+
+ TrafficSelector nodePortSelector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPSrc(IpPrefix.valueOf(nodeIpPrefix))
+ .matchIPDst(IpPrefix.valueOf(dstNode.podCidr()))
+ .build();
+
+ k8sFlowRuleService.setRule(
+ appId,
+ dstNode.tunBridge(),
+ nodePortSelector,
+ treatment,
+ PRIORITY_INTER_NODE_RULE,
+ TUN_ENTRY_TABLE,
+ install);
}
}
}
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/util/K8sNetworkingUtil.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/util/K8sNetworkingUtil.java
index 938629f..f691b1f 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/util/K8sNetworkingUtil.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/util/K8sNetworkingUtil.java
@@ -295,6 +295,19 @@
}
/**
+ * Obtains gateway IP address of the given subnet.
+ *
+ * @param cidr CIDR
+ * @return gateway IP address
+ */
+ public static IpAddress getGatewayIp(String cidr) {
+ SubnetUtils utils = new SubnetUtils(cidr);
+ utils.setInclusiveHostCount(false);
+ SubnetUtils.SubnetInfo info = utils.getInfo();
+ return IpAddress.valueOf(info.getLowAddress());
+ }
+
+ /**
* Obtains flow group key from the given id.
*
* @param groupId flow group identifier
diff --git a/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/util/K8sNetworkUtilTest.java b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/util/K8sNetworkUtilTest.java
index b90e770..ee34e47 100644
--- a/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/util/K8sNetworkUtilTest.java
+++ b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/util/K8sNetworkUtilTest.java
@@ -24,6 +24,7 @@
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.existingContainerPortByMac;
+import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.getGatewayIp;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.getSubnetIps;
/**
@@ -49,6 +50,13 @@
assertEquals(0, dClassIps.size());
}
+ @Test
+ public void testGetGatewayIp() {
+ String classCidr = "10.10.10.0/24";
+ IpAddress gatewayIp = getGatewayIp(classCidr);
+ assertEquals("10.10.10.1", gatewayIp.toString());
+ }
+
/**
* Tests the existing container port by MAC.
*/
diff --git a/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/DefaultK8sNode.java b/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/DefaultK8sNode.java
index c4d7ac3..e914977 100644
--- a/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/DefaultK8sNode.java
+++ b/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/DefaultK8sNode.java
@@ -80,7 +80,7 @@
private final DeviceId tunBridge;
private final IpAddress managementIp;
private final IpAddress dataIp;
- private final IpAddress nodeIp;
+ private final K8sNodeInfo nodeInfo;
private final K8sNodeState state;
private final K8sExternalNetwork extNetwork;
private final String podCidr;
@@ -103,7 +103,7 @@
* @param tunBridge tunnel bridge
* @param managementIp management IP address
* @param dataIp data IP address
- * @param nodeIp node IP address
+ * @param nodeInfo node info
* @param state node state
* @param extNetwork external network
* @param podCidr POD CIDR
@@ -112,7 +112,7 @@
int segmentId, Mode mode, DeviceId intgBridge,
DeviceId extBridge, DeviceId localBridge,
DeviceId tunBridge, IpAddress managementIp,
- IpAddress dataIp, IpAddress nodeIp, K8sNodeState state,
+ IpAddress dataIp, K8sNodeInfo nodeInfo, K8sNodeState state,
K8sExternalNetwork extNetwork, String podCidr) {
this.clusterName = clusterName;
this.hostname = hostname;
@@ -125,7 +125,7 @@
this.tunBridge = tunBridge;
this.managementIp = managementIp;
this.dataIp = dataIp;
- this.nodeIp = nodeIp;
+ this.nodeInfo = nodeInfo;
this.state = state;
this.extNetwork = extNetwork;
this.podCidr = podCidr;
@@ -237,7 +237,7 @@
.tunBridge(tunBridge)
.managementIp(managementIp)
.dataIp(dataIp)
- .nodeIp(nodeIp)
+ .nodeInfo(nodeInfo)
.state(state)
.extBridgeIp(extNetwork.extBridgeIp())
.extGatewayIp(extNetwork.extGatewayIp())
@@ -261,7 +261,7 @@
.tunBridge(tunBridge)
.managementIp(managementIp)
.dataIp(dataIp)
- .nodeIp(nodeIp)
+ .nodeInfo(nodeInfo)
.state(state)
.extBridgeIp(extNetwork.extBridgeIp())
.extGatewayIp(extNetwork.extGatewayIp())
@@ -285,7 +285,7 @@
.tunBridge(tunBridge)
.managementIp(managementIp)
.dataIp(dataIp)
- .nodeIp(nodeIp)
+ .nodeInfo(nodeInfo)
.state(state)
.extBridgeIp(extNetwork.extBridgeIp())
.extGatewayIp(extNetwork.extGatewayIp())
@@ -309,7 +309,7 @@
.tunBridge(deviceId)
.managementIp(managementIp)
.dataIp(dataIp)
- .nodeIp(nodeIp)
+ .nodeInfo(nodeInfo)
.state(state)
.extBridgeIp(extNetwork.extBridgeIp())
.extGatewayIp(extNetwork.extGatewayIp())
@@ -330,8 +330,22 @@
}
@Override
+ public K8sNodeInfo nodeInfo() {
+ return nodeInfo;
+ }
+
+ @Override
public IpAddress nodeIp() {
- return nodeIp;
+ return nodeInfo.nodeIp();
+ }
+
+ @Override
+ public MacAddress nodeMac() {
+ if (nodeInfo == null) {
+ return null;
+ } else {
+ return nodeInfo.nodeMac();
+ }
}
@Override
@@ -358,7 +372,7 @@
.tunBridge(tunBridge)
.managementIp(managementIp)
.dataIp(dataIp)
- .nodeIp(nodeIp)
+ .nodeInfo(nodeInfo)
.state(newState)
.extBridgeIp(extNetwork.extBridgeIp())
.extGatewayIp(extNetwork.extGatewayIp())
@@ -382,7 +396,7 @@
.tunBridge(tunBridge)
.managementIp(managementIp)
.dataIp(dataIp)
- .nodeIp(nodeIp)
+ .nodeInfo(nodeInfo)
.state(state)
.extBridgeIp(extNetwork.extBridgeIp())
.extGatewayIp(extNetwork.extGatewayIp())
@@ -393,6 +407,30 @@
}
@Override
+ public K8sNode updateNodeInfo(K8sNodeInfo newNodeInfo) {
+ return new Builder()
+ .hostname(hostname)
+ .clusterName(clusterName)
+ .type(type)
+ .segmentId(segmentId)
+ .mode(mode)
+ .intgBridge(intgBridge)
+ .extBridge(extBridge)
+ .localBridge(localBridge)
+ .tunBridge(tunBridge)
+ .managementIp(managementIp)
+ .dataIp(dataIp)
+ .nodeInfo(newNodeInfo)
+ .state(state)
+ .extBridgeIp(extNetwork.extBridgeIp())
+ .extGatewayIp(extNetwork.extGatewayIp())
+ .extGatewayMac(extNetwork.extGatewayMac())
+ .extIntf(extNetwork.extIntf())
+ .podCidr(podCidr)
+ .build();
+ }
+
+ @Override
public PortNumber grePortNum() {
return tunnelPortNum(grePortName());
}
@@ -617,20 +655,20 @@
}
@Override
- public MacAddress portMacByName(String portName) {
+ public MacAddress portMacByName(DeviceId deviceId, String portName) {
if (portName == null) {
return null;
} else {
- return macAddress(this.intgBridge, portName);
+ return macAddress(deviceId, portName);
}
}
@Override
- public PortNumber portNumByName(String portName) {
+ public PortNumber portNumByName(DeviceId deviceId, String portName) {
if (portName == null) {
return null;
} else {
- return portNumber(this.intgBridge, portName);
+ return portNumber(deviceId, portName);
}
}
@@ -843,7 +881,7 @@
tunBridge.equals(that.tunBridge) &&
managementIp.equals(that.managementIp) &&
dataIp.equals(that.dataIp) &&
- nodeIp.equals(that.nodeIp) &&
+ nodeInfo.equals(that.nodeInfo) &&
extNetwork.equals(that.extNetwork) &&
podCidr.equals(that.podCidr) &&
state == that.state;
@@ -855,7 +893,7 @@
@Override
public int hashCode() {
return Objects.hash(clusterName, hostname, type, segmentId, mode, intgBridge, extBridge,
- localBridge, tunBridge, managementIp, dataIp, nodeIp, state, extNetwork, podCidr);
+ localBridge, tunBridge, managementIp, dataIp, nodeInfo, state, extNetwork, podCidr);
}
@Override
@@ -872,7 +910,7 @@
.add("tunBridge", tunBridge)
.add("managementIp", managementIp)
.add("dataIp", dataIp)
- .add("nodeIp", nodeIp)
+ .add("nodeInfo", nodeInfo)
.add("state", state)
.add("extBridgeIp", extNetwork.extBridgeIp())
.add("extGatewayIp", extNetwork.extGatewayIp())
@@ -937,7 +975,7 @@
.extIntf(node.extIntf())
.managementIp(node.managementIp())
.dataIp(node.dataIp())
- .nodeIp(node.nodeIp())
+ .nodeInfo(node.nodeInfo())
.state(node.state())
.extBridgeIp(node.extBridgeIp())
.extGatewayIp(node.extGatewayIp())
@@ -959,7 +997,7 @@
private DeviceId tunBridge;
private IpAddress managementIp;
private IpAddress dataIp;
- private IpAddress nodeIp;
+ private K8sNodeInfo nodeInfo;
private K8sNodeState state;
private K8sApiConfig apiConfig;
private String extIntf;
@@ -978,7 +1016,7 @@
checkArgument(type != null, NOT_NULL_MSG, "type");
checkArgument(state != null, NOT_NULL_MSG, "state");
checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
- checkArgument(nodeIp != null, NOT_NULL_MSG, "node IP");
+ checkArgument(nodeInfo != null, NOT_NULL_MSG, "node info");
if (StringUtils.isEmpty(clusterName)) {
clusterName = DEFAULT_CLUSTER_NAME;
@@ -1006,7 +1044,7 @@
tunBridge,
managementIp,
dataIp,
- nodeIp,
+ nodeInfo,
state,
extNetwork,
podCidr);
@@ -1079,8 +1117,8 @@
}
@Override
- public Builder nodeIp(IpAddress nodeIp) {
- this.nodeIp = nodeIp;
+ public Builder nodeInfo(K8sNodeInfo nodeInfo) {
+ this.nodeInfo = nodeInfo;
return this;
}
diff --git a/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/K8sNode.java b/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/K8sNode.java
index 5c13bc1..4609f25 100644
--- a/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/K8sNode.java
+++ b/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/K8sNode.java
@@ -187,13 +187,27 @@
IpAddress dataIp();
/**
+ * Returns the kubernetes node info.
+ *
+ * @return node info; null if node info not exists
+ */
+ K8sNodeInfo nodeInfo();
+
+ /**
* Returns the kubernetes node IP address.
*
- * @return ip address; null if node has no IP address
+ * @return node IP address; null if the node IP not exists
*/
IpAddress nodeIp();
/**
+ * Returns the kubernetes node MAC address.
+ *
+ * @return node MAC address; null if the node MAC not exists
+ */
+ MacAddress nodeMac();
+
+ /**
* Returns the initialization state of the node.
*
* @return node state
@@ -224,6 +238,14 @@
K8sNode updateExtGatewayMac(MacAddress macAddress);
/**
+ * Returns new kubernetes node instance with given node info.
+ *
+ * @param nodeInfo updated node info
+ * @return updated kubernetes node
+ */
+ K8sNode updateNodeInfo(K8sNodeInfo nodeInfo);
+
+ /**
* Returns GRE port name.
*
* @return GRE port name
@@ -268,18 +290,20 @@
/**
* Returns the port MAC address with the given patch port name.
*
+ * @param deviceId device identifier
* @param portName patch port name
* @return port MAC address
*/
- MacAddress portMacByName(String portName);
+ MacAddress portMacByName(DeviceId deviceId, String portName);
/**
* Returns the port number with the given patch port name.
*
+ * @param deviceId device identifier
* @param portName patch port name
* @return port number
*/
- PortNumber portNumByName(String portName);
+ PortNumber portNumByName(DeviceId deviceId, String portName);
/**
* Return the port number of integration bridge's entry port.
@@ -677,12 +701,12 @@
Builder dataIp(IpAddress dataIp);
/**
- * Returns the kubernetes node builder with supplied node IP address.
+ * Returns the kubernetes node builder with supplied node info.
*
- * @param nodeIp node IP address
+ * @param nodeInfo node info
* @return kubernetes node builder
*/
- Builder nodeIp(IpAddress nodeIp);
+ Builder nodeInfo(K8sNodeInfo nodeInfo);
/**
* Returns kubernetes node builder with supplied node state.
diff --git a/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/K8sNodeInfo.java b/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/K8sNodeInfo.java
new file mode 100644
index 0000000..ecd266e
--- /dev/null
+++ b/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/K8sNodeInfo.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.k8snode.api;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+
+import java.util.Objects;
+
+/**
+ * Kubernetes node info class.
+ */
+public class K8sNodeInfo {
+ private final IpAddress nodeIp;
+ private final MacAddress nodeMac;
+
+ /**
+ * Default constructor.
+ *
+ * @param nodeIp node IP address
+ * @param nodeMac node MAC address
+ */
+ public K8sNodeInfo(IpAddress nodeIp, MacAddress nodeMac) {
+ this.nodeIp = nodeIp;
+ this.nodeMac = nodeMac;
+ }
+
+ /**
+ * Obtains Kubernetes node IP address.
+ *
+ * @return node IP address
+ */
+ public IpAddress nodeIp() {
+ return nodeIp;
+ }
+
+ /**
+ * Obtains Kubernetes node MAC address.
+ *
+ * @return node MAC address
+ */
+ public MacAddress nodeMac() {
+ return nodeMac;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ K8sNodeInfo that = (K8sNodeInfo) o;
+ return Objects.equals(nodeIp, that.nodeIp) &&
+ Objects.equals(nodeMac, that.nodeMac);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nodeIp, nodeMac);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("nodeIp", nodeIp)
+ .add("nodeMac", nodeMac)
+ .toString();
+ }
+}
\ No newline at end of file
diff --git a/apps/k8s-node/api/src/test/java/org/onosproject/k8snode/api/DefaultK8sNodeTest.java b/apps/k8s-node/api/src/test/java/org/onosproject/k8snode/api/DefaultK8sNodeTest.java
index dec1d48..c953c8b 100644
--- a/apps/k8s-node/api/src/test/java/org/onosproject/k8snode/api/DefaultK8sNodeTest.java
+++ b/apps/k8s-node/api/src/test/java/org/onosproject/k8snode/api/DefaultK8sNodeTest.java
@@ -20,6 +20,7 @@
import org.junit.Test;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
import org.onosproject.k8snode.api.K8sNode.Type;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
@@ -52,6 +53,8 @@
private static final IpAddress MANAGEMENT_IP = IpAddress.valueOf("10.10.10.10");
private static final IpAddress DATA_IP = IpAddress.valueOf("20.20.20.20");
private static final IpAddress NODE_IP = IpAddress.valueOf("30.30.30.30");
+ private static final MacAddress NODE_MAC = MacAddress.valueOf("fa:00:00:00:00:08");
+ private static final K8sNodeInfo NODE_INFO = new K8sNodeInfo(NODE_IP, NODE_MAC);
private static final String BRIDGE_INTF_1 = "eth1";
private static final String BRIDGE_INTF_2 = "eth2";
@@ -78,6 +81,7 @@
DEVICE_1,
BRIDGE_INTF_1,
TEST_IP,
+ NODE_INFO,
INIT,
EXT_BRIDGE_IP_1,
EXT_GATEWAY_IP_1,
@@ -93,6 +97,7 @@
DEVICE_1,
BRIDGE_INTF_1,
TEST_IP,
+ NODE_INFO,
INIT,
EXT_BRIDGE_IP_1,
EXT_GATEWAY_IP_1,
@@ -108,6 +113,7 @@
DEVICE_2,
BRIDGE_INTF_2,
TEST_IP,
+ NODE_INFO,
INIT,
EXT_BRIDGE_IP_2,
EXT_GATEWAY_IP_2,
@@ -125,7 +131,7 @@
.segmentId(SEGMENT_ID_1)
.managementIp(MANAGEMENT_IP)
.dataIp(DATA_IP)
- .nodeIp(NODE_IP)
+ .nodeInfo(NODE_INFO)
.intgBridge(DEVICE_1.id())
.extBridge(DEVICE_1.id())
.localBridge(DEVICE_1.id())
@@ -198,7 +204,7 @@
.extIntf(BRIDGE_INTF_1)
.managementIp(TEST_IP)
.dataIp(TEST_IP)
- .nodeIp(NODE_IP)
+ .nodeInfo(NODE_INFO)
.state(INIT)
.extBridgeIp(EXT_BRIDGE_IP_1)
.extGatewayIp(EXT_GATEWAY_IP_1)
@@ -222,7 +228,7 @@
.extIntf(BRIDGE_INTF_1)
.managementIp(TEST_IP)
.dataIp(TEST_IP)
- .nodeIp(NODE_IP)
+ .nodeInfo(NODE_INFO)
.state(INIT)
.extBridgeIp(EXT_BRIDGE_IP_1)
.extGatewayIp(EXT_GATEWAY_IP_1)
@@ -247,7 +253,7 @@
.tunBridge(DEVICE_1.id())
.extIntf(BRIDGE_INTF_1)
.dataIp(TEST_IP)
- .nodeIp(NODE_IP)
+ .nodeInfo(NODE_INFO)
.state(INIT)
.extBridgeIp(EXT_BRIDGE_IP_1)
.extGatewayIp(EXT_GATEWAY_IP_1)
@@ -261,7 +267,7 @@
assertEquals(node.type(), MINION);
assertEquals(node.managementIp(), MANAGEMENT_IP);
assertEquals(node.dataIp(), DATA_IP);
- assertEquals(node.nodeIp(), NODE_IP);
+ assertEquals(node.nodeInfo(), NODE_INFO);
}
private static Device createDevice(long devIdNum) {
@@ -278,7 +284,7 @@
private static K8sNode createNode(String clusterName, String hostname, Type type,
int segmentId, Device intgBridge, Device extBridge,
Device localBridge, Device tunBridge, String bridgeIntf,
- IpAddress ipAddr, K8sNodeState state,
+ IpAddress ipAddr, K8sNodeInfo info, K8sNodeState state,
IpAddress extBridgeIp, IpAddress extGatewayIp,
String podCidr) {
return DefaultK8sNode.builder()
@@ -293,7 +299,7 @@
.extIntf(bridgeIntf)
.managementIp(ipAddr)
.dataIp(ipAddr)
- .nodeIp(ipAddr)
+ .nodeInfo(info)
.state(state)
.extBridgeIp(extBridgeIp)
.extGatewayIp(extGatewayIp)
diff --git a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sNodeCodec.java b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sNodeCodec.java
index 4f4e6bf..6e00655 100644
--- a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sNodeCodec.java
+++ b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sNodeCodec.java
@@ -24,6 +24,7 @@
import org.onosproject.codec.JsonCodec;
import org.onosproject.k8snode.api.DefaultK8sNode;
import org.onosproject.k8snode.api.K8sNode;
+import org.onosproject.k8snode.api.K8sNodeInfo;
import org.onosproject.k8snode.api.K8sNodeState;
import org.onosproject.net.DeviceId;
import org.slf4j.Logger;
@@ -49,6 +50,7 @@
private static final String MANAGEMENT_IP = "managementIp";
private static final String DATA_IP = "dataIp";
private static final String NODE_IP = "nodeIp";
+ private static final String NODE_MAC = "nodeMac";
private static final String INTEGRATION_BRIDGE = "integrationBridge";
private static final String EXTERNAL_BRIDGE = "externalBridge";
private static final String LOCAL_BRIDGE = "localBridge";
@@ -95,6 +97,10 @@
result.put(DATA_IP, node.dataIp().toString());
}
+ if (node.nodeMac() != null) {
+ result.put(NODE_MAC, node.nodeMac().toString());
+ }
+
if (node.extIntf() != null) {
result.put(EXTERNAL_INTF, node.extIntf());
}
@@ -135,13 +141,15 @@
String nIp = nullIsIllegal(json.get(NODE_IP).asText(),
NODE_IP + MISSING_MESSAGE);
+ K8sNodeInfo nodeInfo = new K8sNodeInfo(IpAddress.valueOf(nIp), null);
+
DefaultK8sNode.Builder nodeBuilder = DefaultK8sNode.builder()
.clusterName(clusterName)
.hostname(hostname)
.type(K8sNode.Type.valueOf(type))
.state(K8sNodeState.INIT)
.managementIp(IpAddress.valueOf(mIp))
- .nodeIp(IpAddress.valueOf(nIp));
+ .nodeInfo(nodeInfo);
if (json.get(DATA_IP) != null) {
nodeBuilder.dataIp(IpAddress.valueOf(json.get(DATA_IP).asText()));
diff --git a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DefaultK8sApiConfigHandler.java b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DefaultK8sApiConfigHandler.java
index 30606f0..c688740 100644
--- a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DefaultK8sApiConfigHandler.java
+++ b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DefaultK8sApiConfigHandler.java
@@ -39,6 +39,7 @@
import org.onosproject.k8snode.api.K8sHostState;
import org.onosproject.k8snode.api.K8sNode;
import org.onosproject.k8snode.api.K8sNodeAdminService;
+import org.onosproject.k8snode.api.K8sNodeInfo;
import org.onosproject.k8snode.api.K8sRouterBridge;
import org.onosproject.k8snode.api.K8sTunnelBridge;
import org.osgi.service.component.annotations.Activate;
@@ -274,7 +275,7 @@
.hostname(hostname)
.managementIp(managementIp)
.dataIp(dataIp)
- .nodeIp(nodeIp)
+ .nodeInfo(new K8sNodeInfo(nodeIp, null))
.extIntf(extIntf)
.type(nodeType)
.segmentId(config.segmentId())
diff --git a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DistributedK8sNodeStore.java b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DistributedK8sNodeStore.java
index 8d3e926..90ec2a0 100644
--- a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DistributedK8sNodeStore.java
+++ b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DistributedK8sNodeStore.java
@@ -25,6 +25,7 @@
import org.onosproject.k8snode.api.K8sExternalNetwork;
import org.onosproject.k8snode.api.K8sNode;
import org.onosproject.k8snode.api.K8sNodeEvent;
+import org.onosproject.k8snode.api.K8sNodeInfo;
import org.onosproject.k8snode.api.K8sNodeState;
import org.onosproject.k8snode.api.K8sNodeStore;
import org.onosproject.k8snode.api.K8sNodeStoreDelegate;
@@ -79,6 +80,7 @@
.register(K8sNode.class)
.register(DefaultK8sNode.class)
.register(K8sNode.Type.class)
+ .register(K8sNodeInfo.class)
.register(K8sNodeState.class)
.register(K8sApiConfig.Mode.class)
.register(K8sExternalNetwork.class)
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeCodecTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeCodecTest.java
index ae31130..d2061d2 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeCodecTest.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeCodecTest.java
@@ -28,6 +28,7 @@
import org.onosproject.core.CoreService;
import org.onosproject.k8snode.api.DefaultK8sNode;
import org.onosproject.k8snode.api.K8sNode;
+import org.onosproject.k8snode.api.K8sNodeInfo;
import org.onosproject.k8snode.api.K8sNodeState;
import org.onosproject.net.DeviceId;
@@ -86,7 +87,7 @@
.state(K8sNodeState.INIT)
.managementIp(IpAddress.valueOf("10.10.10.1"))
.dataIp(IpAddress.valueOf("20.20.20.2"))
- .nodeIp(IpAddress.valueOf("30.30.30.3"))
+ .nodeInfo(new K8sNodeInfo(IpAddress.valueOf("30.30.30.3"), null))
.intgBridge(DeviceId.deviceId("kbr-int"))
.extIntf("eth1")
.extBridgeIp(IpAddress.valueOf("10.10.10.5"))
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sNodeManagerTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sNodeManagerTest.java
index e336164..a1df1b6 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sNodeManagerTest.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sNodeManagerTest.java
@@ -23,6 +23,7 @@
import org.onlab.junit.TestUtils;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
import org.onosproject.cluster.ClusterServiceAdapter;
import org.onosproject.cluster.LeadershipServiceAdapter;
import org.onosproject.core.ApplicationId;
@@ -32,6 +33,7 @@
import org.onosproject.k8snode.api.DefaultK8sNode;
import org.onosproject.k8snode.api.K8sNode;
import org.onosproject.k8snode.api.K8sNodeEvent;
+import org.onosproject.k8snode.api.K8sNodeInfo;
import org.onosproject.k8snode.api.K8sNodeListener;
import org.onosproject.k8snode.api.K8sNodeState;
import org.onosproject.net.DefaultDevice;
@@ -74,6 +76,10 @@
private static final String MINION_2_HOSTNAME = "minion_2";
private static final String MINION_3_HOSTNAME = "minion_3";
+ private static final IpAddress NODE_IP = IpAddress.valueOf("30.30.30.30");
+ private static final MacAddress NODE_MAC = MacAddress.valueOf("fa:00:00:00:00:08");
+ private static final K8sNodeInfo NODE_INFO = new K8sNodeInfo(NODE_IP, NODE_MAC);
+
private static final Device MINION_1_INTG_DEVICE = createDevice(1);
private static final Device MINION_2_INTG_DEVICE = createDevice(2);
private static final Device MINION_3_INTG_DEVICE = createDevice(3);
@@ -100,6 +106,7 @@
MINION_1_LOCAL_DEVICE,
MINION_1_TUN_DEVICE,
IpAddress.valueOf("10.100.0.1"),
+ NODE_INFO,
INIT
);
private static final K8sNode MINION_2 = createNode(
@@ -111,6 +118,7 @@
MINION_2_LOCAL_DEVICE,
MINION_2_TUN_DEVICE,
IpAddress.valueOf("10.100.0.2"),
+ NODE_INFO,
INIT
);
private static final K8sNode MINION_3 = createNode(
@@ -122,6 +130,7 @@
MINION_3_LOCAL_DEVICE,
MINION_3_TUN_DEVICE,
IpAddress.valueOf("10.100.0.3"),
+ NODE_INFO,
COMPLETE
);
@@ -349,7 +358,8 @@
private static K8sNode createNode(String clusterName, String hostname, K8sNode.Type type,
Device intgBridge, Device extBridge,
Device localBridge, Device tunBridge,
- IpAddress ipAddr, K8sNodeState state) {
+ IpAddress ipAddr, K8sNodeInfo nodeInfo,
+ K8sNodeState state) {
return DefaultK8sNode.builder()
.hostname(hostname)
.clusterName(clusterName)
@@ -360,7 +370,7 @@
.tunBridge(tunBridge.id())
.managementIp(ipAddr)
.dataIp(ipAddr)
- .nodeIp(ipAddr)
+ .nodeInfo(nodeInfo)
.state(state)
.build();
}
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/web/K8sNodeWebResourceTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/web/K8sNodeWebResourceTest.java
index 9908e99..b99c881 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/web/K8sNodeWebResourceTest.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/web/K8sNodeWebResourceTest.java
@@ -30,6 +30,7 @@
import org.onosproject.k8snode.api.K8sApiConfigAdminService;
import org.onosproject.k8snode.api.K8sNode;
import org.onosproject.k8snode.api.K8sNodeAdminService;
+import org.onosproject.k8snode.api.K8sNodeInfo;
import org.onosproject.k8snode.api.K8sNodeState;
import org.onosproject.k8snode.codec.HostNodesInfoCodec;
import org.onosproject.k8snode.codec.K8sApiConfigCodec;
@@ -97,7 +98,7 @@
.type(K8sNode.Type.MINION)
.dataIp(IpAddress.valueOf("10.134.34.222"))
.managementIp(IpAddress.valueOf("10.134.231.30"))
- .nodeIp(IpAddress.valueOf("30.30.30.3"))
+ .nodeInfo(new K8sNodeInfo(IpAddress.valueOf("30.30.30.3"), null))
.intgBridge(DeviceId.deviceId("of:00000000000000a1"))
.extBridge(DeviceId.deviceId("of:00000000000000b1"))
.state(K8sNodeState.INIT)
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
index cf776d1..1ee3ee2 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
@@ -102,6 +102,9 @@
public static final int PRIORITY_CNI_PT_ARP_RULE = 41500;
public static final int PRIORITY_CNI_PT_IP_RULE = 41400;
+ public static final int PRIORITY_CNI_PT_NODE_PORT_IP_RULE = 42500;
+ public static final int PRIORITY_CNI_PT_NODE_PORT_ARP_RULE = 43000;
+ public static final int PRIORITY_CNI_PT_NODE_PORT_ARP_EXT_RULE = 41500;
// flow table index
public static final int STAT_INBOUND_TABLE = 0;
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackK8sIntegrationService.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackK8sIntegrationService.java
index 660764e..15c1ec0 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackK8sIntegrationService.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackK8sIntegrationService.java
@@ -51,4 +51,20 @@
void uninstallCniPtNodeRules(IpAddress k8sNodeIp, IpPrefix podCidr,
IpPrefix serviceCidr, IpAddress podGatewayIp,
String osK8sIntPortName, MacAddress k8sIntOsPortMac);
+
+ /**
+ * Installs K8S pass-through CNI related node port flow rules.
+ *
+ * @param k8sNodeIp kubernetes node IP address
+ * @param osK8sExtPortName openstack k8s external patch port name
+ */
+ void installCniPtNodePortRules(IpAddress k8sNodeIp, String osK8sExtPortName);
+
+ /**
+ * Uninstalls K8S pass-through CNI related node port flow rules.
+ *
+ * @param k8sNodeIp kubernetes node IP address
+ * @param osK8sExtPortName openstack k8s external patch port name
+ */
+ void uninstallCniPtNodePortRules(IpAddress k8sNodeIp, String osK8sExtPortName);
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackK8sIntegrationManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackK8sIntegrationManager.java
index 2f5c1d1..ab99742 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackK8sIntegrationManager.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackK8sIntegrationManager.java
@@ -16,14 +16,19 @@
package org.onosproject.openstacknetworking.impl;
+import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.TpPort;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
-import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
@@ -38,6 +43,7 @@
import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackNodeService;
+import org.openstack4j.model.network.Network;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
@@ -45,12 +51,22 @@
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
+import java.util.Map;
+import java.util.Objects;
+
+import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.FLAT_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CNI_PT_IP_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CNI_PT_NODE_PORT_ARP_EXT_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CNI_PT_NODE_PORT_ARP_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CNI_PT_NODE_PORT_IP_RULE;
import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.FLAT;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.shiftIpDomain;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.structurePortName;
+import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildPortRangeMatches;
+import static org.onosproject.openstacknode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -65,7 +81,10 @@
protected final Logger log = getLogger(getClass());
- public static final String SHIFTED_IP_PREFIX = "172.10";
+ private static final String SHIFTED_IP_PREFIX = "172.10";
+ private static final int NODE_PORT_MIN = 30000;
+ private static final int NODE_PORT_MAX = 32767;
+ public static final String NODE_FAKE_IP_STR = "172.172.172.172";
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected CoreService coreService;
@@ -85,6 +104,9 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected InstancePortService instancePortService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected DeviceService deviceService;
+
private ApplicationId appId;
@Activate
@@ -119,22 +141,30 @@
setPodToNodeIpRules(k8sNodeIp, podGatewayIp, osK8sIntPortName, false);
}
+ @Override
+ public void installCniPtNodePortRules(IpAddress k8sNodeIp, String osK8sExtPortName) {
+ setNodePortIngressRules(k8sNodeIp, osK8sExtPortName, true);
+ setNodePortEgressRules(k8sNodeIp, osK8sExtPortName, true);
+
+ setArpRequestRules(k8sNodeIp, osK8sExtPortName, true);
+ setArpReplyRules(k8sNodeIp, osK8sExtPortName, true);
+ }
+
+ @Override
+ public void uninstallCniPtNodePortRules(IpAddress k8sNodeIp, String osK8sExtPortName) {
+ setNodePortIngressRules(k8sNodeIp, osK8sExtPortName, false);
+ setNodePortEgressRules(k8sNodeIp, osK8sExtPortName, false);
+
+ setArpRequestRules(k8sNodeIp, osK8sExtPortName, false);
+ setArpReplyRules(k8sNodeIp, osK8sExtPortName, false);
+ }
+
private void setNodeToPodIpRules(IpAddress k8sNodeIp,
IpPrefix podCidr, IpPrefix serviceCidr,
IpAddress gatewayIp, String osK8sIntPortName,
MacAddress k8sIntOsPortMac, boolean install) {
- InstancePort instPort = instancePortService.instancePorts().stream().filter(p -> {
- OpenstackNetwork.Type netType = osNetworkService.networkType(p.networkId());
- return netType == FLAT && p.ipAddress().equals(k8sNodeIp);
- }).findAny().orElse(null);
-
- if (instPort == null) {
- return;
- }
-
- DeviceId deviceId = instPort.deviceId();
- OpenstackNode osNode = osNodeService.node(deviceId);
+ OpenstackNode osNode = osNodeByNodeIp(k8sNodeIp);
if (osNode == null) {
return;
@@ -203,17 +233,13 @@
private void setPodToNodeIpRules(IpAddress k8sNodeIp, IpAddress gatewayIp,
String osK8sIntPortName, boolean install) {
- InstancePort instPort = instancePortService.instancePorts().stream().filter(p -> {
- OpenstackNetwork.Type netType = osNetworkService.networkType(p.networkId());
- return netType == FLAT && p.ipAddress().equals(k8sNodeIp);
- }).findAny().orElse(null);
+ InstancePort instPort = instPortByNodeIp(k8sNodeIp);
if (instPort == null) {
return;
}
- DeviceId deviceId = instPort.deviceId();
- OpenstackNode osNode = osNodeService.node(deviceId);
+ OpenstackNode osNode = osNodeByNodeIp(k8sNodeIp);
if (osNode == null) {
return;
@@ -247,4 +273,233 @@
install
);
}
+
+ private void setNodePortIngressRules(IpAddress k8sNodeIp,
+ String osK8sExtPortName,
+ boolean install) {
+ OpenstackNode osNode = osNodeByNodeIp(k8sNodeIp);
+
+ if (osNode == null) {
+ return;
+ }
+
+ PortNumber osK8sExtPortNum = portNumberByNodeIpAndPortName(k8sNodeIp, osK8sExtPortName);
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(osK8sExtPortNum)
+ .build();
+
+ Map<TpPort, TpPort> portRangeMatchMap =
+ buildPortRangeMatches(NODE_PORT_MIN, NODE_PORT_MAX);
+
+ portRangeMatchMap.forEach((key, value) -> {
+ TrafficSelector.Builder tcpSelectorBuilder = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(IpPrefix.valueOf(k8sNodeIp, 32))
+ .matchIPProtocol(IPv4.PROTOCOL_TCP)
+ .matchTcpDstMasked(key, value);
+
+ TrafficSelector.Builder udpSelectorBuilder = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(IpPrefix.valueOf(k8sNodeIp, 32))
+ .matchIPProtocol(IPv4.PROTOCOL_UDP)
+ .matchUdpDstMasked(key, value);
+
+ osFlowRuleService.setRule(
+ appId,
+ osNode.intgBridge(),
+ tcpSelectorBuilder.build(),
+ treatment,
+ PRIORITY_CNI_PT_NODE_PORT_IP_RULE,
+ FLAT_TABLE,
+ install
+ );
+
+ osFlowRuleService.setRule(
+ appId,
+ osNode.intgBridge(),
+ udpSelectorBuilder.build(),
+ treatment,
+ PRIORITY_CNI_PT_NODE_PORT_IP_RULE,
+ FLAT_TABLE,
+ install
+ );
+ });
+ }
+
+ private void setNodePortEgressRules(IpAddress k8sNodeIp,
+ String osK8sExtPortName,
+ boolean install) {
+ InstancePort instPort = instPortByNodeIp(k8sNodeIp);
+
+ if (instPort == null) {
+ return;
+ }
+
+ OpenstackNode osNode = osNodeByNodeIp(k8sNodeIp);
+
+ if (osNode == null) {
+ return;
+ }
+
+ PortNumber osK8sExtPortNum = portNumberByNodeIpAndPortName(k8sNodeIp, osK8sExtPortName);
+
+ Port phyPort = phyPortByInstPort(instPort);
+
+ if (phyPort == null) {
+ log.warn("No phys interface found for instance port {}", instPort);
+ return;
+ }
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchInPort(osK8sExtPortNum)
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setEthSrc(instPort.macAddress())
+ .setOutput(phyPort.number())
+ .build();
+
+ osFlowRuleService.setRule(
+ appId,
+ osNode.intgBridge(),
+ selector,
+ treatment,
+ PRIORITY_CNI_PT_NODE_PORT_IP_RULE,
+ DHCP_TABLE,
+ install
+ );
+ }
+
+ private void setArpRequestRules(IpAddress k8sNodeIp, String osK8sExtPortName, boolean install) {
+ InstancePort instPort = instPortByNodeIp(k8sNodeIp);
+
+ if (instPort == null) {
+ return;
+ }
+
+ OpenstackNode osNode = osNodeByNodeIp(k8sNodeIp);
+
+ if (osNode == null) {
+ return;
+ }
+
+ PortNumber osK8sExtPortNum = portNumberByNodeIpAndPortName(k8sNodeIp, osK8sExtPortName);
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_ARP)
+ .matchArpOp(ARP.OP_REQUEST)
+ .matchInPort(osK8sExtPortNum)
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .transition(STAT_FLAT_OUTBOUND_TABLE)
+ .build();
+
+ osFlowRuleService.setRule(
+ appId,
+ osNode.intgBridge(),
+ selector,
+ treatment,
+ PRIORITY_CNI_PT_NODE_PORT_ARP_RULE,
+ DHCP_TABLE,
+ install
+ );
+
+ Port phyPort = phyPortByInstPort(instPort);
+
+ if (phyPort == null) {
+ log.warn("No phys interface found for instance port {}", instPort);
+ return;
+ }
+
+ TrafficTreatment extTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(phyPort.number())
+ .build();
+
+ osFlowRuleService.setRule(
+ appId,
+ osNode.intgBridge(),
+ selector,
+ extTreatment,
+ PRIORITY_CNI_PT_NODE_PORT_ARP_EXT_RULE,
+ FLAT_TABLE,
+ install
+ );
+ }
+
+ private void setArpReplyRules(IpAddress k8sNodeIp, String osK8sExtPortName, boolean install) {
+ OpenstackNode osNode = osNodeByNodeIp(k8sNodeIp);
+
+ if (osNode == null) {
+ return;
+ }
+
+ PortNumber osK8sExtPortNum = portNumberByNodeIpAndPortName(k8sNodeIp, osK8sExtPortName);
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_ARP)
+ .matchArpOp(ARP.OP_REPLY)
+ .matchArpTpa(Ip4Address.valueOf(NODE_FAKE_IP_STR))
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(osK8sExtPortNum)
+ .build();
+
+ osFlowRuleService.setRule(
+ appId,
+ osNode.intgBridge(),
+ selector,
+ treatment,
+ PRIORITY_CNI_PT_NODE_PORT_ARP_RULE,
+ FLAT_TABLE,
+ install
+ );
+ }
+
+ private InstancePort instPortByNodeIp(IpAddress k8sNodeIp) {
+ return instancePortService.instancePorts().stream().filter(p -> {
+ OpenstackNetwork.Type netType = osNetworkService.networkType(p.networkId());
+ return netType == FLAT && p.ipAddress().equals(k8sNodeIp);
+ }).findAny().orElse(null);
+ }
+
+ private OpenstackNode osNodeByNodeIp(IpAddress k8sNodeIp) {
+ InstancePort instPort = instPortByNodeIp(k8sNodeIp);
+
+ if (instPort == null) {
+ return null;
+ }
+
+ return osNodeService.node(instPort.deviceId());
+ }
+
+ private PortNumber portNumberByNodeIpAndPortName(IpAddress k8sNodeIp, String portName) {
+ OpenstackNode osNode = osNodeByNodeIp(k8sNodeIp);
+
+ if (osNode == null) {
+ return null;
+ }
+
+ return osNode.portNumByName(portName);
+ }
+
+ private Port phyPortByInstPort(InstancePort instPort) {
+ Network network = osNetworkService.network(instPort.networkId());
+
+ if (network == null) {
+ log.warn("The network does not exist");
+ return null;
+ }
+
+ return deviceService.getPorts(instPort.deviceId()).stream()
+ .filter(port -> {
+ String annotPortName = port.annotations().value(PORT_NAME);
+ String portName = structurePortName(INTEGRATION_TO_PHYSICAL_PREFIX
+ + network.getProviderPhyNet());
+ return Objects.equals(annotPortName, portName);
+ }).findAny().orElse(null);
+ }
}
\ No newline at end of file
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
index 8e8bc83..70f197a 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
@@ -17,7 +17,6 @@
package org.onosproject.openstacknetworking.impl;
import com.google.common.base.Strings;
-import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
@@ -119,6 +118,7 @@
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_SECURITY_GROUP_DEFAULT;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValueAsBoolean;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
+import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildPortRangeMatches;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.computeCtMaskFlag;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.computeCtStateFlag;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.niciraConnTrackTreatmentBuilder;
@@ -140,14 +140,7 @@
private static final int VM_IP_PREFIX = 32;
- private static final String STR_ZERO = "0";
- private static final String STR_ONE = "1";
private static final String STR_NULL = "null";
- private static final String STR_PADDING = "0000000000000000";
- private static final int MASK_BEGIN_IDX = 0;
- private static final int MASK_MAX_IDX = 16;
- private static final int MASK_RADIX = 2;
- private static final int PORT_RADIX = 16;
/** Apply OpenStack security group rule for VM traffic. */
private boolean useSecurityGroup = USE_SECURITY_GROUP_DEFAULT;
@@ -845,88 +838,6 @@
});
}
- private int binLower(String binStr, int bits) {
- StringBuilder outBin = new StringBuilder(
- binStr.substring(MASK_BEGIN_IDX, MASK_MAX_IDX - bits));
- for (int i = 0; i < bits; i++) {
- outBin.append(STR_ZERO);
- }
-
- return Integer.parseInt(outBin.toString(), MASK_RADIX);
- }
-
- private int binHigher(String binStr, int bits) {
- StringBuilder outBin = new StringBuilder(
- binStr.substring(MASK_BEGIN_IDX, MASK_MAX_IDX - bits));
- for (int i = 0; i < bits; i++) {
- outBin.append(STR_ONE);
- }
-
- return Integer.parseInt(outBin.toString(), MASK_RADIX);
- }
-
- private int testMasks(String binStr, int start, int end) {
- int mask = MASK_BEGIN_IDX;
- for (; mask <= MASK_MAX_IDX; mask++) {
- int maskStart = binLower(binStr, mask);
- int maskEnd = binHigher(binStr, mask);
- if (maskStart < start || maskEnd > end) {
- return mask - 1;
- }
- }
-
- return mask;
- }
-
- private String getMask(int bits) {
- switch (bits) {
- case 0: return "ffff";
- case 1: return "fffe";
- case 2: return "fffc";
- case 3: return "fff8";
- case 4: return "fff0";
- case 5: return "ffe0";
- case 6: return "ffc0";
- case 7: return "ff80";
- case 8: return "ff00";
- case 9: return "fe00";
- case 10: return "fc00";
- case 11: return "f800";
- case 12: return "f000";
- case 13: return "e000";
- case 14: return "c000";
- case 15: return "8000";
- case 16: return "0000";
- default: return null;
- }
- }
-
- private Map<TpPort, TpPort> buildPortRangeMatches(int portMin, int portMax) {
-
- boolean processing = true;
- int start = portMin;
- Map<TpPort, TpPort> portMaskMap = Maps.newHashMap();
- while (processing) {
- String minStr = Integer.toBinaryString(start);
- String binStrMinPadded = STR_PADDING.substring(minStr.length()) + minStr;
-
- int mask = testMasks(binStrMinPadded, start, portMax);
- int maskStart = binLower(binStrMinPadded, mask);
- int maskEnd = binHigher(binStrMinPadded, mask);
-
- log.debug("start : {} port/mask = {} / {} ", start, getMask(mask), maskStart);
- portMaskMap.put(TpPort.tpPort(maskStart), TpPort.tpPort(
- Integer.parseInt(Objects.requireNonNull(getMask(mask)), PORT_RADIX)));
-
- start = maskEnd + 1;
- if (start > portMax) {
- processing = false;
- }
- }
-
- return portMaskMap;
- }
-
private class InternalInstancePortListener implements InstancePortListener {
@Override
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java
index de5295c..aca49de 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.openstacknetworking.util;
+import com.google.common.collect.Maps;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
@@ -38,6 +39,8 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_LOAD;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA;
@@ -82,6 +85,14 @@
private static final int PORT_MIN_FLAG = 4;
private static final int PORT_MAX_FLAG = 5;
+ private static final String STR_ZERO = "0";
+ private static final String STR_ONE = "1";
+ private static final String STR_PADDING = "0000000000000000";
+ private static final int MASK_BEGIN_IDX = 0;
+ private static final int MASK_MAX_IDX = 16;
+ private static final int MASK_RADIX = 2;
+ private static final int PORT_RADIX = 16;
+
// Refer to http://openvswitch.org/support/dist-docs/ovs-fields.7.txt for the values
public static final long CT_STATE_NONE = 0;
public static final long CT_STATE_NEW = 0x01;
@@ -405,6 +416,95 @@
return ctMaskFlag;
}
+ /**
+ * Computes port and port mask value from port min/max values.
+ *
+ * @param portMin port min value
+ * @param portMax port max value
+ * @return Port Mask value
+ */
+ public static Map<TpPort, TpPort> buildPortRangeMatches(int portMin, int portMax) {
+
+ boolean processing = true;
+ int start = portMin;
+ Map<TpPort, TpPort> portMaskMap = Maps.newHashMap();
+ while (processing) {
+ String minStr = Integer.toBinaryString(start);
+ String binStrMinPadded = STR_PADDING.substring(minStr.length()) + minStr;
+
+ int mask = testMasks(binStrMinPadded, start, portMax);
+ int maskStart = binLower(binStrMinPadded, mask);
+ int maskEnd = binHigher(binStrMinPadded, mask);
+
+ log.debug("start : {} port/mask = {} / {} ", start, getMask(mask), maskStart);
+ portMaskMap.put(TpPort.tpPort(maskStart), TpPort.tpPort(
+ Integer.parseInt(Objects.requireNonNull(getMask(mask)), PORT_RADIX)));
+
+ start = maskEnd + 1;
+ if (start > portMax) {
+ processing = false;
+ }
+ }
+
+ return portMaskMap;
+ }
+
+ private static int binLower(String binStr, int bits) {
+ StringBuilder outBin = new StringBuilder(
+ binStr.substring(MASK_BEGIN_IDX, MASK_MAX_IDX - bits));
+ for (int i = 0; i < bits; i++) {
+ outBin.append(STR_ZERO);
+ }
+
+ return Integer.parseInt(outBin.toString(), MASK_RADIX);
+ }
+
+ private static int binHigher(String binStr, int bits) {
+ StringBuilder outBin = new StringBuilder(
+ binStr.substring(MASK_BEGIN_IDX, MASK_MAX_IDX - bits));
+ for (int i = 0; i < bits; i++) {
+ outBin.append(STR_ONE);
+ }
+
+ return Integer.parseInt(outBin.toString(), MASK_RADIX);
+ }
+
+ private static int testMasks(String binStr, int start, int end) {
+ int mask = MASK_BEGIN_IDX;
+ for (; mask <= MASK_MAX_IDX; mask++) {
+ int maskStart = binLower(binStr, mask);
+ int maskEnd = binHigher(binStr, mask);
+ if (maskStart < start || maskEnd > end) {
+ return mask - 1;
+ }
+ }
+
+ return mask;
+ }
+
+ private static String getMask(int bits) {
+ switch (bits) {
+ case 0: return "ffff";
+ case 1: return "fffe";
+ case 2: return "fffc";
+ case 3: return "fff8";
+ case 4: return "fff0";
+ case 5: return "ffe0";
+ case 6: return "ffc0";
+ case 7: return "ff80";
+ case 8: return "ff00";
+ case 9: return "fe00";
+ case 10: return "fc00";
+ case 11: return "f800";
+ case 12: return "f000";
+ case 13: return "e000";
+ case 14: return "c000";
+ case 15: return "8000";
+ case 16: return "0000";
+ default: return null;
+ }
+ }
+
private static boolean checkTreatmentResolver(Device device) {
if (device == null || !device.is(ExtensionTreatmentResolver.class)) {
log.warn("Nicira extension treatment is not supported");
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/web/OpenstackK8sIntegrationWebResource.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/web/OpenstackK8sIntegrationWebResource.java
index c38984b..ef3353b 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/web/OpenstackK8sIntegrationWebResource.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/web/OpenstackK8sIntegrationWebResource.java
@@ -45,6 +45,7 @@
private static final String K8S_NODE_IP = "k8sNodeIp";
private static final String OS_K8S_INT_PORT_NAME = "osK8sIntPortName";
+ private static final String OS_K8S_EXT_PORT_NAME = "osK8sExtPortName";
private static final String POD_CIDR = "podCidr";
private static final String SERVICE_CIDR = "serviceCidr";
private static final String POD_GW_IP = "podGwIp";
@@ -56,7 +57,7 @@
/**
* Installs CNI pass-through related flow rules for each kubernetes nodes.
*
- * @param input JSON string
+ * @param input JSON string
* @return 200 ok, 400 BAD_REQUEST if the json is malformed
* @throws IOException exception
*/
@@ -82,9 +83,9 @@
}
/**
- * Installs CNI pass-through related flow rules for each kubernetes nodes.
+ * Uninstalls CNI pass-through related flow rules for each kubernetes nodes.
*
- * @param input JSON string
+ * @param input JSON string
* @return 200 ok, 400 BAD_REQUEST if the json is malformed
* @throws IOException exception
*/
@@ -108,4 +109,50 @@
return Response.ok().build();
}
+
+ /**
+ * Installs CNI pass-through related node port flow rules.
+ *
+ * @param input JSON string
+ * @return 200 ok, 400 BAD_REQUEST if the json is malformed
+ * @throws IOException exception
+ */
+ @PUT
+ @Path("nodeport/pt-install")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response installCniPtNodePortRules(InputStream input) throws IOException {
+ log.trace("Install K8S CNI pass-through node port rules");
+
+ JsonNode json = readTreeFromStream(mapper().enable(INDENT_OUTPUT), input);
+ IpAddress k8sNodeIp = IpAddress.valueOf(json.get(K8S_NODE_IP).asText());
+ String osK8sExtPortName = json.get(OS_K8S_EXT_PORT_NAME).asText();
+
+ intService.installCniPtNodePortRules(k8sNodeIp, osK8sExtPortName);
+
+ return Response.ok().build();
+ }
+
+ /**
+ * Uninstalls CNI pass-through related node port flow rules.
+ *
+ * @param input JSON string
+ * @return 200 ok, 400 BAD_REQUEST if the json is malformed
+ * @throws IOException exception
+ */
+ @PUT
+ @Path("nodeport/pt-uninstall")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response uninstallCniPtNodePortRules(InputStream input) throws IOException {
+ log.trace("Uninstall K8S CNI pass-through node port rules");
+
+ JsonNode json = readTreeFromStream(mapper().enable(INDENT_OUTPUT), input);
+ IpAddress k8sNodeIp = IpAddress.valueOf(json.get(K8S_NODE_IP).asText());
+ String osK8sExtPortName = json.get(OS_K8S_EXT_PORT_NAME).asText();
+
+ intService.uninstallCniPtNodePortRules(k8sNodeIp, osK8sExtPortName);
+
+ return Response.ok().build();
+ }
}