Implement NodeIP to ServiceIP translation feature
Change-Id: I49bda2cddfb1c22b362b4b48105efd316c3dad36
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 419e7eb..8de62c8 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
@@ -45,9 +45,12 @@
public static final String SHIFTED_IP_CIDR = "172.10.0.0/16";
public static final String SHIFTED_IP_PREFIX = "172.10";
+ public static final String NODE_IP_PREFIX = "182";
public static final String SRC = "src";
public static final String DST = "dst";
+ public static final String A_CLASS = "a";
+ public static final String B_CLASS = "b";
public static final String PORT_NAME_PREFIX_CONTAINER = "veth";
@@ -79,6 +82,9 @@
public static final int PRIORITY_ARP_FLOOD_RULE = 39000;
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;
// flow table index
public static final int STAT_INBOUND_TABLE = 0;
@@ -100,5 +106,8 @@
public static final int VTAP_OUTBOUND_MIRROR_TABLE = 72;
public static final int FORWARDING_TABLE = 80;
public static final int ERROR_TABLE = 100;
- public static final int GW_COMMON_TABLE = 0;
+
+ public static final int EXT_ENTRY_TABLE = 0;
+ public static final int POD_RESOLUTION_TABLE = 11;
+ public static final int INBOUND_TABLE = 10;
}
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
new file mode 100644
index 0000000..c8a0802
--- /dev/null
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sNodePortHandler.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2019-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.k8snetworking.impl;
+
+import io.fabric8.kubernetes.api.model.Service;
+import io.fabric8.kubernetes.api.model.ServicePort;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.TpPort;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cfg.ConfigProperty;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.k8snetworking.api.K8sFlowRuleService;
+import org.onosproject.k8snetworking.api.K8sNetworkService;
+import org.onosproject.k8snetworking.api.K8sServiceEvent;
+import org.onosproject.k8snetworking.api.K8sServiceListener;
+import org.onosproject.k8snetworking.api.K8sServiceService;
+import org.onosproject.k8snode.api.K8sNode;
+import org.onosproject.k8snode.api.K8sNodeEvent;
+import org.onosproject.k8snode.api.K8sNodeListener;
+import org.onosproject.k8snode.api.K8sNodeService;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.slf4j.Logger;
+
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.k8snetworking.api.Constants.B_CLASS;
+import static org.onosproject.k8snetworking.api.Constants.DST;
+import static org.onosproject.k8snetworking.api.Constants.EXT_ENTRY_TABLE;
+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_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.util.K8sNetworkingUtil.getBclassIpPrefixFromCidr;
+import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.getPropertyValue;
+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.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provides service port exposure using node port.
+ */
+@Component(immediate = true)
+public class K8sNodePortHandler {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final String NODE_PORT_TYPE = "NodePort";
+ private static final String TCP = "TCP";
+ private static final String UDP = "UDP";
+ 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;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected ComponentConfigService configService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected DriverService driverService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected LeadershipService leadershipService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected MastershipService mastershipService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected ClusterService clusterService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected K8sNodeService k8sNodeService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected K8sNetworkService k8sNetworkService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected K8sServiceService k8sServiceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected K8sFlowRuleService k8sFlowRuleService;
+
+ private final InternalK8sServiceListener k8sServiceListener =
+ new InternalK8sServiceListener();
+ private final InternalK8sNodeListener k8sNodeListener =
+ new InternalK8sNodeListener();
+ private final ExecutorService eventExecutor = newSingleThreadExecutor(
+ groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
+
+ private ApplicationId appId;
+ private NodeId localNodeId;
+
+ @Activate
+ protected void activate() {
+ appId = coreService.registerApplication(K8S_NETWORKING_APP_ID);
+
+ localNodeId = clusterService.getLocalNode().id();
+ leadershipService.runForLeadership(appId.name());
+ k8sNodeService.addListener(k8sNodeListener);
+ k8sServiceService.addListener(k8sServiceListener);
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ k8sNodeService.removeListener(k8sNodeListener);
+ k8sServiceService.removeListener(k8sServiceListener);
+ leadershipService.withdraw(appId.name());
+ eventExecutor.shutdown();
+
+ log.info("Stopped");
+ }
+
+ private void processNodePortEvent(K8sNode k8sNode, Service service, boolean install) {
+
+ 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);
+ }
+
+ 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);
+ } else {
+ setIntgToExtRemoteRules(k8sNode, n, getServiceCidr(), fullCidr, install);
+ }
+ });
+
+ setDefaultExtEgrRule(k8sNode, install);
+ }
+
+ private void setDefaultExtEgrRule(K8sNode k8sNode, boolean install) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.LOCAL)
+ .matchEthType(Ethernet.TYPE_IPV4);
+
+ 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()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPSrc(IpPrefix.valueOf(serviceCidr))
+ .matchIPDst(IpPrefix.valueOf(shiftedCidr));
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+ .setOutput(k8sNode.intgToExtPatchPortNum());
+
+ 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());
+
+ // TODO: need to consider other network types
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+ .extension(remote, k8sNodeLocal.intgBridge())
+ .setOutput(k8sNodeLocal.vxlanPortNum());
+
+ 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,
+ install);
+ }
+
+ private void setNodeToServiceRules(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)
+ .matchIPDst(IpPrefix.valueOf(k8sNode.extBridgeIp(), HOST_CIDR));
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+ .setIpDst(IpAddress.valueOf(clusterIp));
+
+ if (TCP.equals(protocol)) {
+ sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP)
+ .matchTcpDst(TpPort.tpPort(nodePort));
+ tBuilder.setTcpDst(TpPort.tpPort(svcPort));
+ } else if (UDP.equals(protocol)) {
+ sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP)
+ .matchUdpDst(TpPort.tpPort(nodePort));
+ tBuilder.setUdpDst(TpPort.tpPort(svcPort));
+ }
+
+ String podCidr = k8sNetworkService.network(k8sNode.hostname()).cidr();
+ String prefix = NODE_IP_PREFIX + "." + podCidr.split("\\.")[2];
+
+ ExtensionTreatment loadTreatment = buildLoadExtension(
+ deviceService.getDevice(deviceId), B_CLASS, SRC, prefix);
+ tBuilder.extension(loadTreatment, deviceId)
+ .setOutput(k8sNode.extToIntgPatchPortNum());
+
+ k8sFlowRuleService.setRule(
+ appId,
+ k8sNode.extBridge(),
+ sBuilder.build(),
+ tBuilder.build(),
+ PRIORITY_NODE_PORT_RULE,
+ EXT_ENTRY_TABLE,
+ install);
+ }
+
+ private void setServiceToNodeLocalRules(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 podCidr = k8sNetworkService.network(k8sNode.hostname()).cidr();
+ String nodePrefix = NODE_IP_PREFIX + "." + podCidr.split("\\.")[2];
+
+ if (extBridgePrefix == 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());
+
+ 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 prefix = getBclassIpPrefixFromCidr(gatewayIp);
+
+ if (prefix == null) {
+ return;
+ }
+
+ ExtensionTreatment loadTreatment = buildLoadExtension(
+ deviceService.getDevice(deviceId), B_CLASS, DST, prefix);
+ tBuilder.extension(loadTreatment, deviceId)
+ .setOutput(k8sNode.extBridgePortNum());
+
+ k8sFlowRuleService.setRule(
+ appId,
+ deviceId,
+ sBuilder.build(),
+ tBuilder.build(),
+ PRIORITY_NODE_PORT_REMOTE_RULE,
+ EXT_ENTRY_TABLE,
+ install);
+ }
+
+ private String getServiceCidr() {
+ Set<ConfigProperty> properties =
+ configService.getProperties(K8sServiceHandler.class.getName());
+ return getPropertyValue(properties, SERVICE_CIDR);
+ }
+
+ private class InternalK8sServiceListener implements K8sServiceListener {
+
+ private boolean isRelevantHelper() {
+ return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
+ }
+
+ @Override
+ public void event(K8sServiceEvent event) {
+ switch (event.type()) {
+ case K8S_SERVICE_CREATED:
+ case K8S_SERVICE_UPDATED:
+ eventExecutor.execute(() -> processServiceCreation(event.subject()));
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void processServiceCreation(Service service) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
+ if (NODE_PORT_TYPE.equals(service.getSpec().getType())) {
+ k8sNodeService.completeNodes().forEach(n ->
+ processNodePortEvent(n, service, true)
+ );
+ }
+ }
+ }
+
+ private class InternalK8sNodeListener implements K8sNodeListener {
+
+ private boolean isRelevantHelper() {
+ return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
+ }
+
+ @Override
+ public void event(K8sNodeEvent event) {
+ switch (event.type()) {
+ case K8S_NODE_COMPLETE:
+ eventExecutor.execute(() -> processNodeCompletion(event.subject()));
+ break;
+ case K8S_NODE_INCOMPLETE:
+ default:
+ break;
+ }
+ }
+
+ private void processNodeCompletion(K8sNode k8sNode) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
+ k8sServiceService.services().stream()
+ .filter(s -> NODE_PORT_TYPE.equals(s.getSpec().getType()))
+ .forEach(s -> processNodePortEvent(k8sNode, s, true));
+ }
+ }
+}
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sRoutingSnatHandler.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sRoutingSnatHandler.java
index 349043f..04913b6 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sRoutingSnatHandler.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sRoutingSnatHandler.java
@@ -60,8 +60,9 @@
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.k8snetworking.api.Constants.DEFAULT_GATEWAY_MAC;
-import static org.onosproject.k8snetworking.api.Constants.GW_COMMON_TABLE;
+import static org.onosproject.k8snetworking.api.Constants.EXT_ENTRY_TABLE;
import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
+import static org.onosproject.k8snetworking.api.Constants.POD_RESOLUTION_TABLE;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_EXTERNAL_ROUTING_RULE;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_STATEFUL_SNAT_RULE;
import static org.onosproject.k8snetworking.api.Constants.ROUTING_TABLE;
@@ -79,9 +80,12 @@
private final Logger log = getLogger(getClass());
- private static final int POD_PREFIX = 32;
+ private static final int HOST_PREFIX = 32;
- private static final int TP_PORT_MINIMUM_NUM = 1025;
+ // we try to avoid port number overlapping with node port (30000 ~ 32767)
+ // in case the user has customized node port range, the following static
+ // value should be changed accordingly
+ private static final int TP_PORT_MINIMUM_NUM = 32768;
private static final int TP_PORT_MAXIMUM_NUM = 65535;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
@@ -180,7 +184,7 @@
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(IpPrefix.valueOf(k8sPort.ipAddress(), POD_PREFIX));
+ .matchIPDst(IpPrefix.valueOf(k8sPort.ipAddress(), HOST_PREFIX));
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
.setOutput(k8sNode.extToIntgPatchPortNum());
@@ -191,7 +195,7 @@
sBuilder.build(),
tBuilder.build(),
PRIORITY_STATEFUL_SNAT_RULE,
- GW_COMMON_TABLE,
+ POD_RESOLUTION_TABLE,
install);
}
@@ -199,15 +203,15 @@
boolean install) {
DeviceId deviceId = k8sNode.extBridge();
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(IpPrefix.valueOf(k8sNode.extBridgeIp(), POD_PREFIX));
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(IpPrefix.valueOf(k8sNode.extBridgeIp(), HOST_PREFIX));
ExtensionTreatment natTreatment = RulePopulatorUtil
.niciraConnTrackTreatmentBuilder(driverService, deviceId)
.commit(false)
.natAction(true)
- .table((short) 0)
+ .table((short) POD_RESOLUTION_TABLE)
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
@@ -221,7 +225,7 @@
sBuilder.build(),
treatment,
PRIORITY_STATEFUL_SNAT_RULE,
- GW_COMMON_TABLE,
+ EXT_ENTRY_TABLE,
install);
}
@@ -236,6 +240,7 @@
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
+ .matchInPort(k8sNode.extToIntgPatchPortNum())
.matchEthDst(DEFAULT_GATEWAY_MAC)
.build();
@@ -264,38 +269,38 @@
selector,
tBuilder.build(),
PRIORITY_STATEFUL_SNAT_RULE,
- GW_COMMON_TABLE,
+ EXT_ENTRY_TABLE,
install);
}
private void setExtIntfArpRule(K8sNode k8sNode, boolean install) {
+ k8sNodeService.completeNodes().forEach(n -> {
+ Device device = deviceService.getDevice(n.extBridge());
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_ARP)
+ .matchArpOp(ARP.OP_REQUEST)
+ .matchArpTpa(Ip4Address.valueOf(k8sNode.extBridgeIp().toString()))
+ .build();
- Device device = deviceService.getDevice(k8sNode.extBridge());
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setArpOp(ARP.OP_REPLY)
+ .extension(buildMoveEthSrcToDstExtension(device), device.id())
+ .extension(buildMoveArpShaToThaExtension(device), device.id())
+ .extension(buildMoveArpSpaToTpaExtension(device), device.id())
+ .setArpSpa(Ip4Address.valueOf(k8sNode.extBridgeIp().toString()))
+ .setArpSha(k8sNode.extBridgeMac())
+ .setOutput(PortNumber.IN_PORT)
+ .build();
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_ARP)
- .matchArpOp(ARP.OP_REQUEST)
- .matchArpTpa(Ip4Address.valueOf(k8sNode.extBridgeIp().toString()))
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setArpOp(ARP.OP_REPLY)
- .extension(buildMoveEthSrcToDstExtension(device), device.id())
- .extension(buildMoveArpShaToThaExtension(device), device.id())
- .extension(buildMoveArpSpaToTpaExtension(device), device.id())
- .setArpSpa(Ip4Address.valueOf(k8sNode.extBridgeIp().toString()))
- .setArpSha(k8sNode.extBridgeMac())
- .setOutput(PortNumber.IN_PORT)
- .build();
-
- k8sFlowRuleService.setRule(
- appId,
- k8sNode.extBridge(),
- selector,
- treatment,
- PRIORITY_STATEFUL_SNAT_RULE,
- GW_COMMON_TABLE,
- install);
+ k8sFlowRuleService.setRule(
+ appId,
+ n.extBridge(),
+ selector,
+ treatment,
+ PRIORITY_STATEFUL_SNAT_RULE,
+ EXT_ENTRY_TABLE,
+ install);
+ });
}
private class InternalK8sNodeListener implements K8sNodeListener {
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sServiceHandler.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sServiceHandler.java
index 9c243f9..f9e0545 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sServiceHandler.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sServiceHandler.java
@@ -86,12 +86,15 @@
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.k8snetworking.api.Constants.A_CLASS;
+import static org.onosproject.k8snetworking.api.Constants.B_CLASS;
import static org.onosproject.k8snetworking.api.Constants.DST;
import static org.onosproject.k8snetworking.api.Constants.JUMP_TABLE;
import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
import static org.onosproject.k8snetworking.api.Constants.NAT_STATEFUL;
import static org.onosproject.k8snetworking.api.Constants.NAT_STATELESS;
import static org.onosproject.k8snetworking.api.Constants.NAT_TABLE;
+import static org.onosproject.k8snetworking.api.Constants.NODE_IP_PREFIX;
import static org.onosproject.k8snetworking.api.Constants.POD_TABLE;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_CIDR_RULE;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_CT_RULE;
@@ -108,6 +111,7 @@
import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.SERVICE_IP_CIDR_DEFAULT;
import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.SERVICE_IP_NAT_MODE;
import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.SERVICE_IP_NAT_MODE_DEFAULT;
+import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.getBclassIpPrefixFromCidr;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.nodeIpGatewayIpMap;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.tunnelPortNumByNetId;
import static org.onosproject.k8snetworking.util.RulePopulatorUtil.CT_NAT_DST_FLAG;
@@ -142,6 +146,10 @@
private static final String UDP = "UDP";
private static final String SERVICE_IP_NAT_MODE = "serviceIpNatMode";
+ private static final String SERVICE_CIDR = "serviceCidr";
+ private static final String B_CLASS_SUFFIX = ".0.0/16";
+ private static final String A_CLASS_SUFFIX = ".0.0.0/8";
+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected CoreService coreService;
@@ -268,15 +276,32 @@
private void setStatelessServiceNatRules(DeviceId deviceId, boolean install) {
- String srcCidr = k8sNetworkService.network(
+ String srcPodCidr = k8sNetworkService.network(
k8sNodeService.node(deviceId).hostname()).cidr();
+ String srcPodPrefix = getBclassIpPrefixFromCidr(srcPodCidr);
+ String fullSrcPodCidr = srcPodPrefix + B_CLASS_SUFFIX;
+ String fullSrcNodeCidr = NODE_IP_PREFIX + A_CLASS_SUFFIX;
+
+ // src: POD -> dst: service (unNAT POD) grouping
+ setSrcDstCidrRules(deviceId, fullSrcPodCidr, serviceCidr, B_CLASS, null,
+ SHIFTED_IP_PREFIX, SRC, JUMP_TABLE, SERVICE_TABLE,
+ PRIORITY_CT_RULE, install);
+ // src: POD (unNAT service) -> dst: shifted POD grouping
+ setSrcDstCidrRules(deviceId, fullSrcPodCidr, SHIFTED_IP_CIDR, B_CLASS, null,
+ srcPodPrefix, DST, JUMP_TABLE, POD_TABLE, PRIORITY_CT_RULE, install);
+
+ // src: node -> dst: service (unNAT POD) grouping
+ setSrcDstCidrRules(deviceId, fullSrcNodeCidr, serviceCidr, A_CLASS,
+ null, null, null, JUMP_TABLE, SERVICE_TABLE,
+ PRIORITY_CT_RULE, install);
+ // src: POD (unNAT service) -> dst: node grouping
+ setSrcDstCidrRules(deviceId, fullSrcPodCidr, fullSrcNodeCidr, A_CLASS,
+ null, null, null, JUMP_TABLE, POD_TABLE,
+ PRIORITY_CT_RULE, install);
k8sNetworkService.networks().forEach(n -> {
- setSrcDstCidrRules(deviceId, n.cidr(), serviceCidr, null, JUMP_TABLE,
- SERVICE_TABLE, PRIORITY_CT_RULE, install);
- setSrcDstCidrRules(deviceId, n.cidr(), SHIFTED_IP_CIDR, null, JUMP_TABLE,
- POD_TABLE, PRIORITY_CT_RULE, install);
- setSrcDstCidrRules(deviceId, srcCidr, n.cidr(), n.segmentId(), ROUTING_TABLE,
+ setSrcDstCidrRules(deviceId, fullSrcPodCidr, n.cidr(), B_CLASS,
+ n.segmentId(), null, null, ROUTING_TABLE,
STAT_OUTBOUND_TABLE, PRIORITY_INTER_ROUTING_RULE, install);
});
@@ -287,8 +312,11 @@
}
private void setSrcDstCidrRules(DeviceId deviceId, String srcCidr,
- String dstCidr, String segId, int installTable,
- int transitTable, int priority, boolean install) {
+ String dstCidr, String cidrClass,
+ String segId, String shiftPrefix,
+ String shiftType, int installTable,
+ int transitTable, int priority,
+ boolean install) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPSrc(IpPrefix.valueOf(srcCidr))
@@ -300,6 +328,13 @@
if (segId != null) {
tBuilder.setTunnelId(Long.valueOf(segId));
}
+
+ if (shiftPrefix != null && shiftType != null) {
+ ExtensionTreatment loadTreatment = buildLoadExtension(
+ deviceService.getDevice(deviceId), cidrClass, shiftType, shiftPrefix);
+ tBuilder.extension(loadTreatment, deviceId);
+ }
+
tBuilder.transition(transitTable);
k8sFlowRuleService.setRule(
@@ -480,11 +515,7 @@
.matchUdpDst(TpPort.tpPort(servicePort));
}
- ExtensionTreatment loadTreatment = buildLoadExtension(
- deviceService.getDevice(deviceId), SRC, SHIFTED_IP_PREFIX);
-
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .extension(loadTreatment, deviceId)
.group(GroupId.valueOf(groupId))
.build();
@@ -514,14 +545,7 @@
.matchUdpSrc(TpPort.tpPort(podPort));
}
- String podIpPrefix = podIp.split("\\.")[0] +
- "." + podIp.split("\\.")[1];
-
- ExtensionTreatment loadTreatment = buildLoadExtension(
- deviceService.getDevice(deviceId), DST, podIpPrefix);
-
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .extension(loadTreatment, deviceId)
.setIpSrc(IpAddress.valueOf(serviceIp))
.transition(ROUTING_TABLE);
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 79a2530..779bbc6 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
@@ -30,6 +30,7 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.k8snetworking.api.K8sFlowRuleService;
+import org.onosproject.k8snetworking.api.K8sNetwork;
import org.onosproject.k8snetworking.api.K8sNetworkService;
import org.onosproject.k8snetworking.api.K8sPort;
import org.onosproject.k8snetworking.api.K8sServiceService;
@@ -71,12 +72,14 @@
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_IP_PREFIX;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_ARP_CONTROL_RULE;
import static org.onosproject.k8snetworking.api.Constants.SERVICE_FAKE_MAC_STR;
import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.ARP_MODE;
import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.ARP_MODE_DEFAULT;
import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.GATEWAY_MAC;
import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.GATEWAY_MAC_DEFAULT;
+import static org.onosproject.k8snetworking.api.Constants.SHIFTED_IP_PREFIX;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.getPropertyValue;
import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.unshiftIpDomain;
@@ -94,8 +97,6 @@
private final Logger log = LoggerFactory.getLogger(getClass());
- private static final String API_SERVER_CLUSTER_IP = "10.96.0.1";
-
private static final String GATEWAY_MAC = "gatewayMac";
private static final String ARP_MODE = "arpMode";
@@ -229,16 +230,17 @@
}
if (replyMac == null) {
- Set<String> unshiftedIps = unshiftIpDomain(targetIp.toString(), k8sNetworkService);
- for (String ip : unshiftedIps) {
+ String cidr = k8sNetworkService.networks().stream()
+ .map(K8sNetwork::cidr).findAny().orElse(null);
+
+ if (cidr != null) {
+ String unshiftedIp = unshiftIpDomain(targetIp.toString(),
+ SHIFTED_IP_PREFIX, cidr);
+
replyMac = k8sNetworkService.ports().stream()
- .filter(p -> p.ipAddress().equals(IpAddress.valueOf(ip)))
+ .filter(p -> p.ipAddress().equals(IpAddress.valueOf(unshiftedIp)))
.map(K8sPort::macAddress)
.findAny().orElse(null);
-
- if (replyMac != null) {
- break;
- }
}
}
@@ -252,6 +254,23 @@
}
if (replyMac == null) {
+ 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);
+
+ if (exBridgeCidr != null) {
+ String extBridgeIp = unshiftIpDomain(targetIp.toString(),
+ nodePrefix, exBridgeCidr);
+
+ replyMac = k8sNodeService.completeNodes().stream()
+ .filter(n -> extBridgeIp.equals(n.extBridgeIp().toString()))
+ .map(K8sNode::extBridgeMac).findAny().orElse(null);
+ }
+ }
+
+ if (replyMac == null) {
replyMac = MacAddress.valueOf(gatewayMac);
}
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingHandler.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingHandler.java
index 04fd07c..409d80b 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingHandler.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/impl/K8sSwitchingHandler.java
@@ -59,7 +59,6 @@
import static org.onosproject.k8snetworking.api.Constants.ACL_EGRESS_TABLE;
import static org.onosproject.k8snetworking.api.Constants.ARP_BROADCAST_MODE;
import static org.onosproject.k8snetworking.api.Constants.ARP_TABLE;
-import static org.onosproject.k8snetworking.api.Constants.DEFAULT_GATEWAY_MAC;
import static org.onosproject.k8snetworking.api.Constants.FORWARDING_TABLE;
import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
import static org.onosproject.k8snetworking.api.Constants.PRIORITY_SWITCHING_RULE;
@@ -265,7 +264,6 @@
private void setExtToIntgTunnelTagFlowRules(K8sNode k8sNode, boolean install) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
- .matchEthSrc(DEFAULT_GATEWAY_MAC)
.matchInPort(k8sNode.intgToExtPatchPortNum())
.build();
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 7325976..a263359 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
@@ -20,13 +20,13 @@
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.util.SubnetUtils;
import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
import org.onosproject.cfg.ConfigProperty;
import org.onosproject.k8snetworking.api.K8sNetwork;
import org.onosproject.k8snetworking.api.K8sNetworkService;
@@ -44,12 +44,12 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static org.onosproject.k8snetworking.api.Constants.PORT_NAME_PREFIX_CONTAINER;
-import static org.onosproject.k8snetworking.api.Constants.SHIFTED_IP_PREFIX;
/**
* An utility that used in kubernetes networking app.
@@ -61,6 +61,14 @@
private static final String COLON_SLASH = "://";
private static final String COLON = ":";
+ 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;
+
private K8sNetworkingUtil() {
}
@@ -288,22 +296,133 @@
}
/**
- * Returns a set of unshifted IP addresses.
+ * Returns an unshifted IP address.
*
- * @param ipAddress shifted IP address
- * @param service kubernetes network service
- * @return unshifted IP addresses
+ * @param ipAddress IP address to be unshifted
+ * @param ipPrefix IP prefix which to be used for unshifting
+ * @param cidr a POD network CIDR
+ * @return unshifted IP address
*/
- public static Set<String> unshiftIpDomain(String ipAddress, K8sNetworkService service) {
+ public static String unshiftIpDomain(String ipAddress,
+ String ipPrefix,
+ String cidr) {
- Set<String> unshiftedIps = Sets.newConcurrentHashSet();
+ String origIpPrefix = cidr.split("\\.")[0] + "." + cidr.split("\\.")[1];
+ return StringUtils.replace(ipAddress, ipPrefix, origIpPrefix);
+ }
- service.networks().forEach(n -> {
- String cidr = n.cidr();
- String origIpPrefix = cidr.split("\\.")[0] + "." + cidr.split("\\.")[1];
- unshiftedIps.add(StringUtils.replace(ipAddress, SHIFTED_IP_PREFIX, origIpPrefix));
- });
+ /**
+ * Returns the B class IP prefix of the given CIDR.
+ *
+ * @param cidr CIDR
+ * @return IP prefix
+ */
+ public static String getBclassIpPrefixFromCidr(String cidr) {
+ if (cidr == null) {
+ return null;
+ }
+ return cidr.split("\\.")[0] + "." + cidr.split("\\.")[1];
+ }
- return unshiftedIps;
+ /**
+ * Returns the A class IP prefix of the given CIDR.
+ *
+ * @param cidr CIDR
+ * @return IP prefix
+ */
+ public static String getAclassIpPrefixFromCidr(String cidr) {
+ if (cidr == null) {
+ return null;
+ }
+ return cidr.split("\\.")[0];
+ }
+
+ /**
+ * Returns the map of port range.
+ *
+ * @param portMin minimum port number
+ * @param portMax maximum port number
+ * @return map of port range
+ */
+ 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;
+ }
}
}
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/util/RulePopulatorUtil.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/util/RulePopulatorUtil.java
index a50d30c..89a2e14 100644
--- a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/util/RulePopulatorUtil.java
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/util/RulePopulatorUtil.java
@@ -39,6 +39,8 @@
import java.util.ArrayList;
import java.util.List;
+import static org.onosproject.k8snetworking.api.Constants.A_CLASS;
+import static org.onosproject.k8snetworking.api.Constants.B_CLASS;
import static org.onosproject.k8snetworking.api.Constants.DST;
import static org.onosproject.k8snetworking.api.Constants.SRC;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_LOAD;
@@ -98,7 +100,8 @@
private static final int SRC_IP = 0x00000e04;
private static final int DST_IP = 0x00001004;
- private static final int OFF_SET_BIT = 16;
+ private static final int A_CLASS_OFF_SET_BIT = 8;
+ private static final int B_CLASS_OFF_SET_BIT = 16;
private static final int REMAINDER_BIT = 16;
// not intended for direct invocation from external
@@ -296,11 +299,13 @@
* Returns the nicira load extension treatment.
*
* @param device device instance
+ * @param cidrClass CIDR class (a | b)
* @param ipType IP type (src|dst)
- * @param shift shift (e.g., 10.10., 20.20.,)
+ * @param shift shift (e.g., 10.10., 20.20., 10, 20,)
* @return load extension treatment
*/
public static ExtensionTreatment buildLoadExtension(Device device,
+ String cidrClass,
String ipType,
String shift) {
if (!checkTreatmentResolver(device)) {
@@ -319,10 +324,16 @@
dst = DST_IP;
}
- long value = calculateUpperBit(shift);
+ long value = calculateUpperBit(cidrClass, shift);
- // we only rewrite the upper 16 bits with value (A.B.X.Y -> C.D.X.Y)
- int ofsNbits = OFF_SET_BIT << 6 | (REMAINDER_BIT - 1);
+ // we only rewrite the upper x bits with value
+ int ofsNbits = 0;
+
+ if (A_CLASS.equals(cidrClass)) {
+ ofsNbits = A_CLASS_OFF_SET_BIT << 6 | (REMAINDER_BIT - 1);
+ } else if (B_CLASS.equals(cidrClass)) {
+ ofsNbits = B_CLASS_OFF_SET_BIT << 6 | (REMAINDER_BIT - 1);
+ }
try {
treatment.setPropertyValue(OFF_SET_N_BITS, ofsNbits);
@@ -336,7 +347,6 @@
}
}
-
/**
* Returns the nicira move source MAC to destination MAC extension treatment.
*
@@ -385,16 +395,24 @@
/**
* Calculate IP address upper string into integer.
*
+ * @param cidrClass CIDR class type
* @param shift IP address upper two octets with dot
* @return calculated integer
*/
- private static int calculateUpperBit(String shift) {
- String[] strArray = shift.split("\\.");
+ private static int calculateUpperBit(String cidrClass, String shift) {
- int firstOctet = Integer.valueOf(strArray[0]);
- int secondOctet = Integer.valueOf(strArray[1]);
+ if (A_CLASS.equals(cidrClass)) {
+ return Integer.valueOf(shift);
+ }
- return firstOctet << 8 | secondOctet;
+ if (B_CLASS.equals(cidrClass)) {
+ String[] strArray = shift.split("\\.");
+ int firstOctet = Integer.valueOf(strArray[0]);
+ int secondOctet = Integer.valueOf(strArray[1]);
+ return firstOctet << 8 | secondOctet;
+ }
+
+ return 0;
}
private static boolean checkTreatmentResolver(Device device) {