Retrieve peer router MAC address using ARP.
Change-Id: I494902d28779288219f631f91080596c7b1ea1fa
(cherry picked from commit 542052721ead4f2b74d954a6328d9de0184d9f65)
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtRouterEvent.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtRouterEvent.java
index e9bb84f..4b8ef56 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtRouterEvent.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtRouterEvent.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.kubevirtnetworking.api;
+import org.onlab.packet.MacAddress;
import org.onosproject.event.AbstractEvent;
import java.util.Set;
@@ -33,6 +34,7 @@
private final String externalNet;
private final String peerRouterIp;
private final String gateway;
+ private final MacAddress peerRouterMac;
/**
* Creates an event of a given type for the specified kubevirt router.
@@ -49,6 +51,7 @@
this.externalNet = null;
this.peerRouterIp = null;
this.gateway = null;
+ this.peerRouterMac = null;
}
/**
@@ -67,7 +70,7 @@
this.externalNet = null;
this.peerRouterIp = null;
this.gateway = null;
-
+ this.peerRouterMac = null;
}
/**
@@ -87,6 +90,7 @@
this.externalNet = null;
this.peerRouterIp = null;
this.gateway = null;
+ this.peerRouterMac = null;
}
/**
@@ -105,6 +109,7 @@
this.externalNet = null;
this.peerRouterIp = null;
this.gateway = null;
+ this.peerRouterMac = null;
}
/**
@@ -115,10 +120,11 @@
* @param externalIp virtual router's IP address included in external network
* @param externalNet external network name
* @param peerRouterIp external peer router IP address
+ * @param peerRouterMac external peer router MAC address
*/
public KubevirtRouterEvent(Type type, KubevirtRouter subject,
String externalIp, String externalNet,
- String peerRouterIp) {
+ String peerRouterIp, MacAddress peerRouterMac) {
super(type, subject);
this.internal = null;
this.podName = null;
@@ -127,6 +133,7 @@
this.externalNet = externalNet;
this.peerRouterIp = peerRouterIp;
this.gateway = null;
+ this.peerRouterMac = peerRouterMac;
}
public KubevirtRouterEvent(Type type, KubevirtRouter subject,
@@ -139,6 +146,7 @@
this.externalIp = null;
this.externalNet = null;
this.peerRouterIp = null;
+ this.peerRouterMac = null;
}
public enum Type {
@@ -270,6 +278,23 @@
return gateway;
}
+ /**
+ * Returns the external peer router IP address.
+ *
+ * @return external peer router IP if exists, null otherwise
+ */
+ public String externalPeerRouterIp() {
+ return peerRouterIp;
+ }
+ /**
+ * Returns the external peer router MAC address.
+ *
+ * @return external peer router MAC if exists, null otherwise
+ */
+ public MacAddress peerRouterMac() {
+ return peerRouterMac;
+ }
+
@Override
public String toString() {
if (floatingIp == null) {
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/DistributedKubevirtRouterStore.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/DistributedKubevirtRouterStore.java
index 8f3fdbd..87de35e 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/DistributedKubevirtRouterStore.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/DistributedKubevirtRouterStore.java
@@ -270,7 +270,8 @@
notifyDelegate(new KubevirtRouterEvent(
KUBEVIRT_ROUTER_EXTERNAL_NETWORK_ATTACHED,
router, entry.getKey(), entry.getValue(),
- newValue.peerRouter().ipAddress().toString())));
+ newValue.peerRouter().ipAddress().toString(),
+ newValue.peerRouter().macAddress())));
}
if (oldValue.external().size() > 0 && newValue.external().size() == 0) {
@@ -279,7 +280,8 @@
notifyDelegate(new KubevirtRouterEvent(
KUBEVIRT_ROUTER_EXTERNAL_NETWORK_DETACHED,
router, entry.getKey(), entry.getValue(),
- oldValue.peerRouter().ipAddress().toString())));
+ oldValue.peerRouter().ipAddress().toString(),
+ oldValue.peerRouter().macAddress())));
}
Set<String> added = new HashSet<>(newValue.internal());
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
index e682029..47bf5cc 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
@@ -84,7 +84,6 @@
import static org.onlab.packet.ICMP.TYPE_ECHO_REPLY;
import static org.onlab.packet.ICMP.TYPE_ECHO_REQUEST;
import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.kubevirtnetworking.api.Constants.FLAT_TABLE;
import static org.onosproject.kubevirtnetworking.api.Constants.FORWARDING_TABLE;
import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
import static org.onosproject.kubevirtnetworking.api.Constants.PRE_FLAT_TABLE;
@@ -664,7 +663,6 @@
KubevirtPort dstPort,
KubevirtNode gatewayNode,
boolean install) {
-
Device gwDevice = deviceService.getDevice(gatewayNode.intgBridge());
if (gwDevice == null) {
@@ -699,7 +697,7 @@
sBuilder.build(),
treatment,
PRIORITY_INTERNAL_ROUTING_RULE,
- FLAT_TABLE,
+ PRE_FLAT_TABLE,
install
);
}
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkManager.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkManager.java
index cc4149e..7b40b01 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkManager.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkManager.java
@@ -21,6 +21,7 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.event.ListenerRegistry;
+import org.onosproject.kubevirtnetworking.api.KubevirtFlowRuleService;
import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
import org.onosproject.kubevirtnetworking.api.KubevirtNetworkAdminService;
import org.onosproject.kubevirtnetworking.api.KubevirtNetworkEvent;
@@ -28,6 +29,10 @@
import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
import org.onosproject.kubevirtnetworking.api.KubevirtNetworkStore;
import org.onosproject.kubevirtnetworking.api.KubevirtNetworkStoreDelegate;
+import org.onosproject.kubevirtnetworking.api.KubevirtRouterService;
+import org.onosproject.kubevirtnode.api.KubevirtNodeService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.packet.PacketService;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
@@ -72,8 +77,23 @@
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
protected KubevirtNetworkStore networkStore;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected KubevirtRouterService routerService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected KubevirtNodeService kubevirtNodeService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected PacketService packetService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected KubevirtFlowRuleService kubevirtFlowRuleService;
+
private final KubevirtNetworkStoreDelegate delegate = new InternalNetworkStorageDelegate();
private ApplicationId appId;
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java
new file mode 100644
index 0000000..fd8cb4a
--- /dev/null
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2021-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.kubevirtnetworking.impl;
+
+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.MacAddress;
+import org.onlab.packet.VlanId;
+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.kubevirtnetworking.api.KubevirtFlowRuleService;
+import org.onosproject.kubevirtnetworking.api.KubevirtNetworkAdminService;
+import org.onosproject.kubevirtnetworking.api.KubevirtPeerRouter;
+import org.onosproject.kubevirtnetworking.api.KubevirtRouter;
+import org.onosproject.kubevirtnetworking.api.KubevirtRouterAdminService;
+import org.onosproject.kubevirtnetworking.api.KubevirtRouterEvent;
+import org.onosproject.kubevirtnetworking.api.KubevirtRouterListener;
+import org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil;
+import org.onosproject.kubevirtnode.api.KubevirtNode;
+import org.onosproject.kubevirtnode.api.KubevirtNodeService;
+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;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.packet.DefaultOutboundPacket;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
+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.nio.ByteBuffer;
+import java.util.Objects;
+import java.util.concurrent.ExecutorService;
+
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.kubevirtnetworking.api.Constants.DEFAULT_GATEWAY_MAC;
+import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
+import static org.onosproject.kubevirtnetworking.api.Constants.PRE_FLAT_TABLE;
+import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Handles arp packet.
+ */
+@Component(immediate = true)
+public class KubevirtRoutingArpHandler {
+ protected final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected ClusterService clusterService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected LeadershipService leadershipService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected PacketService packetService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected KubevirtRouterAdminService kubevirtRouterService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected KubevirtNetworkAdminService kubevirtNetworkService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected KubevirtNodeService kubevirtNodeService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected KubevirtFlowRuleService kubevirtFlowRuleService;
+
+ private final ExecutorService eventExecutor = newSingleThreadExecutor(
+ groupedThreads(this.getClass().getSimpleName(), "event-handler"));
+
+ private final PacketProcessor packetProcessor = new InternalPacketProcessor();
+
+ private final InternalRouterEventListener kubevirtRouterlistener = new InternalRouterEventListener();
+
+ private ApplicationId appId;
+ private NodeId localNodeId;
+
+
+ @Activate
+ protected void activate() {
+ appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
+ localNodeId = clusterService.getLocalNode().id();
+ leadershipService.runForLeadership(appId.name());
+
+ packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
+ kubevirtRouterService.addListener(kubevirtRouterlistener);
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ leadershipService.withdraw(appId.name());
+ packetService.removeProcessor(packetProcessor);
+ kubevirtRouterService.removeListener(kubevirtRouterlistener);
+
+ eventExecutor.shutdown();
+
+ log.info("Stopped");
+ }
+ /**
+ * Triggers ARP request to retrieve the peer router mac address.
+ *
+ * @param router kubevirt router
+ * @param peerRouterIp peer router IP address
+ */
+ private void retrievePeerRouterMac(KubevirtRouter router, IpAddress peerRouterIp) {
+
+ log.info("Sending ARP request to the peer router {} to retrieve the MAC address.",
+ peerRouterIp.getIp4Address().toString());
+ String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
+
+ if (routerSnatIp == null) {
+ return;
+ }
+
+ IpAddress sourceIp = IpAddress.valueOf(routerSnatIp);
+
+ MacAddress sourceMac = DEFAULT_GATEWAY_MAC;
+ Ethernet ethRequest = ARP.buildArpRequest(sourceMac.toBytes(),
+ sourceIp.toOctets(),
+ peerRouterIp.toOctets(), VlanId.NO_VID);
+
+ KubevirtNode gatewayNode = kubevirtNodeService.node(router.electedGateway());
+
+ if (gatewayNode == null) {
+ return;
+ }
+
+ PortNumber externalPatchPortNum = KubevirtNetworkingUtil.externalPatchPortNum(deviceService, gatewayNode);
+
+ if (externalPatchPortNum == null) {
+ return;
+ }
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(externalPatchPortNum)
+ .build();
+
+ packetService.emit(new DefaultOutboundPacket(
+ gatewayNode.intgBridge(),
+ treatment,
+ ByteBuffer.wrap(ethRequest.serialize())));
+ }
+
+ /**
+ * Sets default ARP flow rule to retrieve peer router mac address.
+ *
+ * @param routerSnatIp route Snat IP
+ * @param peerRouterIp peer router IP
+ * @param gatewayNodeId gateway node
+ * @param install install if true, uninstall otherwise
+ */
+ private void setRuleArpRequestToController(IpAddress routerSnatIp,
+ IpAddress peerRouterIp,
+ String gatewayNodeId,
+ boolean install) {
+ KubevirtNode gatewayNode = kubevirtNodeService.node(gatewayNodeId);
+ if (gatewayNode == null) {
+ return;
+ }
+
+ if (routerSnatIp == null) {
+ return;
+ }
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(EthType.EtherType.ARP.ethType().toShort())
+ .matchArpOp(ARP.OP_REPLY)
+ .matchArpSpa(peerRouterIp.getIp4Address())
+ .matchArpTpa(routerSnatIp.getIp4Address())
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .punt()
+ .build();
+
+ kubevirtFlowRuleService.setRule(
+ appId,
+ gatewayNode.intgBridge(),
+ selector,
+ treatment,
+ PRIORITY_ARP_GATEWAY_RULE,
+ PRE_FLAT_TABLE,
+ install
+ );
+ }
+
+ private class InternalRouterEventListener implements KubevirtRouterListener {
+ private boolean isRelevantHelper() {
+ return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
+ }
+
+ @Override
+ public void event(KubevirtRouterEvent event) {
+ switch (event.type()) {
+ case KUBEVIRT_GATEWAY_NODE_ATTACHED:
+ case KUBEVIRT_ROUTER_EXTERNAL_NETWORK_ATTACHED:
+ eventExecutor.execute(() -> processRouterExternalNetAttachedOrGwAttached(event.subject()));
+ break;
+ case KUBEVIRT_ROUTER_EXTERNAL_NETWORK_DETACHED:
+ eventExecutor.execute(() -> processRouterExternalNetDetached(event.subject(),
+ event.externalIp(), event.externalPeerRouterIp()));
+ break;
+ case KUBEVIRT_GATEWAY_NODE_DETACHED:
+ eventExecutor.execute(() -> processRouterGatewayNodeDetached(event.subject(), event.gateway()));
+ break;
+ default:
+ //do nothing
+ break;
+ }
+ }
+
+ private void processRouterExternalNetAttachedOrGwAttached(KubevirtRouter router) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+ KubevirtNode gatewayNode = kubevirtNodeService.node(router.electedGateway());
+
+ if (gatewayNode == null) {
+ return;
+ }
+
+ String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
+ if (routerSnatIp == null) {
+ return;
+ }
+
+ if (router.peerRouter() != null &&
+ router.peerRouter().macAddress() == null &&
+ router.peerRouter().ipAddress() != null) {
+ setRuleArpRequestToController(IpAddress.valueOf(routerSnatIp),
+ router.peerRouter().ipAddress(), gatewayNode.hostname(), true);
+
+ retrievePeerRouterMac(router, router.peerRouter().ipAddress());
+ }
+ }
+
+ private void processRouterExternalNetDetached(KubevirtRouter router, String routerSnatIp,
+ String peerRouterIp) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+ if (router.electedGateway() == null) {
+ return;
+ }
+ KubevirtNode gatewayNode = kubevirtNodeService.node(router.electedGateway());
+
+ if (gatewayNode == null) {
+ return;
+ }
+
+ if (routerSnatIp == null || peerRouterIp == null) {
+ return;
+ }
+ setRuleArpRequestToController(IpAddress.valueOf(routerSnatIp),
+ IpAddress.valueOf(peerRouterIp), gatewayNode.hostname(), false);
+ }
+
+ private void processRouterGatewayNodeDetached(KubevirtRouter router, String detachedGatewayNode) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+ if (detachedGatewayNode == null) {
+ return;
+ }
+ String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
+ if (routerSnatIp == null) {
+ return;
+ }
+
+ if (router.peerRouter() != null && router.peerRouter().ipAddress() != null) {
+ setRuleArpRequestToController(IpAddress.valueOf(routerSnatIp),
+ router.peerRouter().ipAddress(), detachedGatewayNode, false);
+ }
+ }
+ }
+
+ private class InternalPacketProcessor implements PacketProcessor {
+ @Override
+ public void process(PacketContext context) {
+ if (context.isHandled()) {
+ return;
+ }
+
+ InboundPacket pkt = context.inPacket();
+ Ethernet ethernet = pkt.parsed();
+
+ if (ethernet != null && ethernet.getEtherType() == Ethernet.TYPE_ARP) {
+ processArpPacket(ethernet);
+ }
+ }
+
+ private void processArpPacket(Ethernet ethernet) {
+ ARP arp = (ARP) ethernet.getPayload();
+
+ if (arp.getOpCode() == ARP.OP_REQUEST) {
+ return;
+ }
+
+ IpAddress spa = Ip4Address.valueOf(arp.getSenderProtocolAddress());
+ MacAddress sha = MacAddress.valueOf(arp.getSenderHardwareAddress());
+
+ IpAddress tpa = Ip4Address.valueOf(arp.getTargetProtocolAddress());
+
+ KubevirtRouter router = kubevirtRouterService.routers().stream()
+ .filter(r -> r.peerRouter() != null && r.peerRouter().ipAddress().equals(spa))
+ .filter(r -> {
+ String routerSnatIp = r.external().keySet().stream().findAny().orElse(null);
+ if (routerSnatIp == null) {
+ return false;
+ }
+ return IpAddress.valueOf(routerSnatIp).equals(tpa);
+ })
+ .findAny().orElse(null);
+
+ if (router == null) {
+ return;
+ }
+
+ KubevirtPeerRouter peerRouter = new KubevirtPeerRouter(spa, sha);
+ log.info("Update peer router mac adress {} to router {}", peerRouter.macAddress(), router.name());
+
+ kubevirtRouterService.updatePeerRouterMac(router.name(), sha);
+ }
+ }
+}
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java
index 20fa0cb..c341037 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java
@@ -82,10 +82,9 @@
import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.VXLAN;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.externalPatchPortNum;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.gatewayNodeForSpecifiedRouter;
-import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getExternalNetworkByRouter;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtPort;
-import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterSnatIpAddress;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterMacAddress;
+import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterSnatIpAddress;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelPort;
import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.CT_NAT_SRC_FLAG;
import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildExtension;
@@ -190,9 +189,19 @@
return;
}
- setArpResponseToPeerRouter(electedGw, Ip4Address.valueOf(routerSnatIp), install);
- setStatefulSnatUpstreamRules(electedGw, router, Ip4Address.valueOf(routerSnatIp), install);
- setStatefulSnatDownstreamRuleForRouter(electedGw, router, Ip4Address.valueOf(routerSnatIp), install);
+ String externalNet = router.external().values().stream().findAny().orElse(null);
+ if (externalNet == null) {
+ return;
+ }
+
+ if (router.peerRouter() != null &&
+ router.peerRouter().ipAddress() != null && router.peerRouter().macAddress() != null) {
+ setArpResponseToPeerRouter(electedGw, Ip4Address.valueOf(routerSnatIp), install);
+ setStatefulSnatUpstreamRules(electedGw, router, Ip4Address.valueOf(routerSnatIp),
+ router.peerRouter().macAddress(), install);
+ setStatefulSnatDownstreamRuleForRouter(electedGw, router, Ip4Address.valueOf(routerSnatIp),
+ kubevirtNetworkService.network(externalNet), install);
+ }
}
private void setArpResponseToPeerRouter(KubevirtNode gatewayNode, Ip4Address ip4Address, boolean install) {
@@ -229,14 +238,15 @@
private void setStatefulSnatUpstreamRules(KubevirtNode gatewayNode,
KubevirtRouter router,
- Ip4Address ip4Address,
+ Ip4Address routerSnatIp,
+ MacAddress peerRouterMacAddress,
boolean install) {
MacAddress routerMacAddress = getRouterMacAddress(router);
if (routerMacAddress == null) {
return;
}
- MacAddress peerRouterMacAddres = router.peerRouter().macAddress();
- if (peerRouterMacAddres == null) {
+
+ if (routerSnatIp == null || peerRouterMacAddress == null) {
return;
}
@@ -251,13 +261,13 @@
.commit(true)
.natFlag(CT_NAT_SRC_FLAG)
.natAction(true)
- .natIp(ip4Address)
+ .natIp(routerSnatIp)
.natPortMin(TpPort.tpPort(TP_PORT_MINIMUM_NUM))
.natPortMax(TpPort.tpPort(TP_PORT_MAXIMUM_NUM))
.build();
tBuilder.extension(natTreatment, gatewayNode.intgBridge())
- .setEthDst(peerRouterMacAddres)
+ .setEthDst(peerRouterMacAddress)
.setEthSrc(DEFAULT_GATEWAY_MAC)
.setOutput(externalPatchPortNum(deviceService, gatewayNode));
@@ -353,7 +363,8 @@
private void setStatefulSnatDownstreamRuleForRouter(KubevirtNode gatewayNode,
KubevirtRouter router,
- IpAddress gatewaySnatIp,
+ IpAddress routerSnatIp,
+ KubevirtNetwork externalNetwork,
boolean install) {
MacAddress routerMacAddress = getRouterMacAddress(router);
@@ -364,8 +375,6 @@
return;
}
- KubevirtNetwork externalNetwork = getExternalNetworkByRouter(kubevirtNetworkService, router);
-
if (externalNetwork == null) {
log.warn("Failed to set stateful snat downstream rule because " +
"there's no external network router {}", router.name());
@@ -383,7 +392,7 @@
sBuilder.matchEthType(Ethernet.TYPE_IPV4);
}
- sBuilder.matchIPDst(IpPrefix.valueOf(gatewaySnatIp, 32));
+ sBuilder.matchIPDst(IpPrefix.valueOf(routerSnatIp, 32));
ExtensionTreatment natTreatment = RulePopulatorUtil
.niciraConnTrackTreatmentBuilder(driverService, gatewayNode.intgBridge())
@@ -439,10 +448,14 @@
event.gateway()));
break;
case KUBEVIRT_ROUTER_EXTERNAL_NETWORK_ATTACHED:
- eventExecutor.execute(() -> processRouterExternalNetAttached(event.subject(), event.externalIp()));
+ eventExecutor.execute(() -> processRouterExternalNetAttached(event.subject(),
+ event.externalIp(), event.externalNet(),
+ event.externalPeerRouterIp(), event.peerRouterMac()));
break;
case KUBEVIRT_ROUTER_EXTERNAL_NETWORK_DETACHED:
- eventExecutor.execute(() -> processRouterExternalNetDetached(event.subject(), event.externalIp()));
+ eventExecutor.execute(() -> processRouterExternalNetDetached(event.subject(),
+ event.externalIp(), event.externalNet(),
+ event.externalPeerRouterIp(), event.peerRouterMac()));
break;
default:
//do nothing
@@ -450,7 +463,8 @@
}
}
- private void processRouterExternalNetAttached(KubevirtRouter router, String externalIp) {
+ private void processRouterExternalNetAttached(KubevirtRouter router, String externalIp, String externalNet,
+ String peerRouterIp, MacAddress peerRouterMac) {
if (!isRelevantHelper()) {
return;
}
@@ -462,10 +476,13 @@
return;
}
- if (router.enableSnat() && router.peerRouter() != null && externalIp != null) {
+ if (router.enableSnat() &&
+ peerRouterIp != null && peerRouterMac != null && externalIp != null && externalNet != null) {
setArpResponseToPeerRouter(electedGw, Ip4Address.valueOf(externalIp), true);
- setStatefulSnatUpstreamRules(electedGw, router, Ip4Address.valueOf(externalIp), true);
- setStatefulSnatDownstreamRuleForRouter(electedGw, router, Ip4Address.valueOf(externalIp), true);
+ setStatefulSnatUpstreamRules(electedGw, router, Ip4Address.valueOf(externalIp),
+ peerRouterMac, true);
+ setStatefulSnatDownstreamRuleForRouter(electedGw, router, Ip4Address.valueOf(externalIp),
+ kubevirtNetworkService.network(externalNet), true);
}
router.internal()
@@ -473,10 +490,6 @@
.filter(networkId -> kubevirtNetworkService.network(networkId) != null)
.map(kubevirtNetworkService::network)
.forEach(network -> {
- String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
- if (routerSnatIp == null) {
- return;
- }
kubevirtPortService.ports(network.networkId()).forEach(kubevirtPort -> {
setStatefulSnatDownStreamRuleForKubevirtPort(router,
electedGw, kubevirtPort, true);
@@ -484,7 +497,8 @@
});
}
- private void processRouterExternalNetDetached(KubevirtRouter router, String externalIp) {
+ private void processRouterExternalNetDetached(KubevirtRouter router, String externalIp, String externalNet,
+ String peerRouterIp, MacAddress peerRouterMac) {
if (!isRelevantHelper()) {
return;
}
@@ -499,10 +513,13 @@
return;
}
- if (router.enableSnat() && router.peerRouter() != null && externalIp != null) {
+ if (router.enableSnat() &&
+ peerRouterIp != null && peerRouterMac != null && externalIp != null && externalNet != null) {
setArpResponseToPeerRouter(electedGw, Ip4Address.valueOf(externalIp), false);
- setStatefulSnatUpstreamRules(electedGw, router, Ip4Address.valueOf(externalIp), false);
- setStatefulSnatDownstreamRuleForRouter(electedGw, router, Ip4Address.valueOf(externalIp), false);
+ setStatefulSnatUpstreamRules(electedGw, router,
+ Ip4Address.valueOf(externalIp), peerRouterMac, false);
+ setStatefulSnatDownstreamRuleForRouter(electedGw, router, Ip4Address.valueOf(externalIp),
+ kubevirtNetworkService.network(externalNet), false);
}
router.internal()
@@ -510,10 +527,6 @@
.filter(networkId -> kubevirtNetworkService.network(networkId) != null)
.map(kubevirtNetworkService::network)
.forEach(network -> {
- String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
- if (routerSnatIp == null) {
- return;
- }
kubevirtPortService.ports(network.networkId()).forEach(kubevirtPort -> {
setStatefulSnatDownStreamRuleForKubevirtPort(router,
electedGw, kubevirtPort, false);
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
index 94a7883..92104a0 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
@@ -42,7 +42,6 @@
import org.onosproject.kubevirtnode.api.KubevirtApiConfigService;
import org.onosproject.kubevirtnode.api.KubevirtNode;
import org.onosproject.kubevirtnode.api.KubevirtNodeService;
-import org.onosproject.kubevirtnode.api.KubevirtPhyInterface;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
@@ -550,13 +549,13 @@
* @return external patch port number
*/
public static PortNumber externalPatchPortNum(DeviceService deviceService, KubevirtNode gatewayNode) {
- KubevirtPhyInterface intf = gatewayNode.phyIntfs().stream().findFirst().orElse(null);
- if (intf == null) {
+ String gatewayBridgeName = gatewayNode.gatewayBridgeName();
+ if (gatewayBridgeName == null) {
log.warn("No external interface is attached to gateway {}", gatewayNode.hostname());
return null;
}
- String patchPortName = "int-to-" + intf.network();
+ String patchPortName = "int-to-" + gatewayBridgeName;
Port port = deviceService.getPorts(gatewayNode.intgBridge()).stream()
.filter(p -> p.isEnabled() &&
Objects.equals(p.annotations().value(PORT_NAME), patchPortName))