This review (1st Review) is part of EVPN_RT5 support in NAT feature.
Changes are made in the NAT code for accomplishing the below
Intra DC Communication:
=========================
For Non-NAPT to NAPT Traffic, Tunnel id will be setting with
Router lPortTag which will be carved out per router if it is part of
L3VpnOverVxlan else tunnel-id will be setting with existing router-id.
Change-Id: Idc5e8b1956311541ae7bae255d023c5f3543f9a3
Signed-off-by: karthikeyan <karthikeyan.k@altencalsoftlabs.com>
Signed-off-by: cgowdru <chetan.arakere@altencalsoftlabs.com>
mdsalManager.syncInstallGroup(groupEntity, 0);
// Install miss entry pointing to group
FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
+ if (flowEntity == null) {
+ LOG.error("NAT Service : Flow entity received as NULL. "
+ + "Cannot proceed with installation of SNAT Flow in table {} which is pointing to Group "
+ + "on Non NAPT DPN {} for router {}", NwConstants.PSNAT_TABLE, dpnId, routerName);
+ return;
+ }
mdsalManager.installFlow(flowEntity);
}
public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}",
- dpId, routerName, groupId);
+ dpId, routerName, groupId);
long routerId = NatUtil.getVpnId(dataBroker, routerName);
List<MatchInfo> matches = new ArrayList<>();
matches.add(MatchEthernetType.IPV4);
matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
List<ActionInfo> actionsInfo = new ArrayList<>();
-
- actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(routerId)));
+ long tunnelId = NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerId);
+ actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(tunnelId)));
LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
actionsInfo.add(new ActionGroup(groupId));
List<InstructionInfo> instructions = new ArrayList<>();
instructions.add(new InstructionApplyActions(actionsInfo));
String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
- NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
- NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
return flowEntity;
LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}",
dpnId, routerName);
FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
+ if (flowEntity == null) {
+ LOG.error("NAT Service : Flow entity received as NULL. "
+ + "Cannot proceed with installation of Terminating Service table {} which is pointing to table {} "
+ + "on DPN {} for router {}", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.OUTBOUND_NAPT_TABLE,
+ dpnId, routerName);
+ return;
+ }
mdsalManager.installFlow(flowEntity);
}
private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
-
- BigInteger routerId = BigInteger.valueOf(NatUtil.getVpnId(dataBroker, routerName));
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
List<MatchInfo> matches = new ArrayList<>();
matches.add(MatchEthernetType.IPV4);
- matches.add(new MatchTunnelId(routerId));
+ long tunnelId = NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerId);
+ matches.add(new MatchTunnelId(BigInteger.valueOf(tunnelId)));
+ String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, tunnelId);
List<InstructionInfo> instructions = new ArrayList<>();
- instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
- MetaDataUtil.METADATA_MASK_VRFID));
+ instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(routerId),
+ MetaDataUtil.METADATA_MASK_VRFID));
instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
- String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
- NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
- NwConstants.COOKIE_TS_TABLE, matches, instructions);
+ NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0, NwConstants.COOKIE_TS_TABLE, matches,
+ instructions);
return flowEntity;
}
.child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ //Release allocated router_lPort_tag from the ID Manager if Router is on L3VPNOverVxlan
+ NatEvpnUtil.releaseLPortTagForRouter(dataBroker, idManager, routerName);
}
public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName,
//Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
// traffic which comes from the VMs of the non NAPT switches)
- String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
+ long tunnelId = NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerId);
+ String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tunnelId);
FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
-
LOG.info("NAT Service : Remove the flow in the {} for the active switch with the DPN ID {} and router ID {}",
NwConstants.INTERNAL_TUNNEL_TABLE, dpnId, routerId);
mdsalManager.removeFlow(tsNatFlowEntity);
}
SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
SessionAddress externalAddress =
- naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
+ naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid,
- routerId, bgpVpnId, externalAddress, internalAddress, protocol, extGwMacAddress);
+ routerId, bgpVpnId, externalAddress, internalAddress, protocol, extGwMacAddress);
NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid,
routerId, bgpVpnId, internalAddress, externalAddress, protocol, extGwMacAddress);
}
LOG.error("Invalid routerId returned for routerName {}", routerName);
return;
}
-
//Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table
String tsFlowRef = externalRouterListener.getFlowRefTs(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}",
- NwConstants.INTERNAL_TUNNEL_TABLE, naptSwitch, routerId);
+ NwConstants.INTERNAL_TUNNEL_TABLE, naptSwitch, routerId);
mdsalManager.removeFlow(tsNatFlowEntity);
-
//Remove the Outbound flow entry which forwards the packet to Outbound NAPT Table
String outboundNatFlowRef = externalRouterListener.getFlowRefOutbound(naptSwitch,
NwConstants.OUTBOUND_NAPT_TABLE, routerId);
//Install the flow in newNaptSwitch Outbound NAPT table.
try {
NaptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NwConstants.OUTBOUND_NAPT_TABLE,
- vpnId, routerId, bgpVpnId, sourceAddress, externalAddress, proto, extGwMacAddress);
+ vpnId, routerId, bgpVpnId, sourceAddress, externalAddress, proto, extGwMacAddress);
} catch (Exception ex) {
LOG.error("Failed to add flow in OUTBOUND_NAPT_TABLE for routerid {} dpnId {} "
- + "ipport {}:{} proto {} extIpport {}:{} BgpVpnId {} - {}",
- routerId, newNaptSwitch, internalIpAddress,
- intportnum, proto, externalAddress, extportNumber, bgpVpnId, ex);
+ + "ipport {}:{} proto {} extIpport {}:{} BgpVpnId {} - {}",
+ routerId, newNaptSwitch, internalIpAddress,
+ intportnum, proto, externalAddress, extportNumber, bgpVpnId, ex);
return false;
}
LOG.debug("Successfully installed a flow in Primary switch {} Outbound NAPT table for router {} "
- + "ipport {}:{} proto {} extIpport {}:{} BgpVpnId {}",
- newNaptSwitch, routerId, internalIpAddress,
- intportnum, proto, externalAddress, extportNumber, bgpVpnId);
+ + "ipport {}:{} proto {} extIpport {}:{} BgpVpnId {}",
+ newNaptSwitch, routerId, internalIpAddress,
+ intportnum, proto, externalAddress, extportNumber, bgpVpnId);
} else {
LOG.error("NewNaptSwitch {} gone down while installing flows from oldNaptswitch {}",
newNaptSwitch, oldNaptSwitch);
if (addordel == NatConstants.ADD_FLOW) {
List<ActionInfo> actionsInfo = new ArrayList<>();
-
- actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(routerVpnId)));
+ long tunnelId = NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerVpnId);
+ actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(tunnelId)));
LOG.debug("Setting the tunnel to the list of action infos {}", actionsInfo);
actionsInfo.add(new ActionGroup(groupId));
List<InstructionInfo> instructions = new ArrayList<>();
instructions.add(new InstructionApplyActions(actionsInfo));
flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
- NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
- NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
} else {
flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
public static final long SNAT_ID_HIGH_VALUE = 225000L;
public static final int DEFAULT_TS_FLOW_PRIORITY = 10;
public static final short DEFAULT_PREFIX = 32;
+ public static final long DEFAULT_L3VNI_VALUE = 0;
// Flow Actions
public static final int ADD_FLOW = 0;
--- /dev/null
+/*
+ * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.natservice.internal;
+
+import com.google.common.base.Optional;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NatEvpnUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NatEvpnUtil.class);
+
+ static long getLPortTagForRouter(String routerIdKey, IdManagerService idManager) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(IfmConstants.IFM_IDPOOL_NAME).setIdKey(routerIdKey)
+ .build();
+ try {
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+ RpcResult<AllocateIdOutput> rpcResult = result.get();
+ return rpcResult.getResult().getIdValue();
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.error("NAT Service : ID manager failed while allocating lport_tag for router {}."
+ + "Exception {}", routerIdKey, e);
+ }
+ return 0;
+ }
+
+ public static void releaseLPortTagForRouter(DataBroker dataBroker, IdManagerService idManager, String routerName) {
+
+ String rd = NatUtil.getVpnRd(dataBroker, routerName);
+ long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
+ if (!NatEvpnUtil.isL3VpnOverVxLan(l3Vni)) {
+ return;
+ }
+ ReleaseIdInput getIdInput = new ReleaseIdInputBuilder()
+ .setPoolName(IfmConstants.IFM_IDPOOL_NAME).setIdKey(routerName)
+ .build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(getIdInput);
+ RpcResult<Void> rpcResult = result.get();
+ if (!rpcResult.isSuccessful()) {
+ LOG.error("NAT Service : ID manager failed while releasing allocated lport_tag for router {}."
+ + "Exception {} ", routerName, rpcResult.getErrors());
+ return;
+ }
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.error("NAT Service : ID manager failed while releasing allocated lport_tag for router {}."
+ + "Exception {}", routerName, e);
+ }
+ }
+
+ public static long getTunnelIdForRouter(IdManagerService idManager, DataBroker dataBroker, String routerName,
+ long routerId) {
+ /* Only if the router is part of an L3VPN-Over-VXLAN, Router_lPort_Tag which will be carved out per router
+ from 'interfaces' POOL and used as tunnel_id. Otherwise we will continue to use router-id as the tunnel-id
+ in the following Flows.
+
+ 1) PSNAT_TABLE (on Non-NAPT) -> Send to Remote Group
+ 2) INTERNAL_TUNNEL_TABLE (on NAPT) -> Send to OUTBOUND_NAPT_TABLE */
+ String rd = NatUtil.getVpnRd(dataBroker, routerName);
+ long l3Vni = getL3Vni(dataBroker, rd);
+ if (isL3VpnOverVxLan(l3Vni)) {
+ long routerLportTag = getLPortTagForRouter(routerName, idManager);
+ if (routerLportTag != 0) {
+ LOG.trace("NAT Service : Successfully allocated Router_lPort_Tag = {} from ID Manager for "
+ + "Router ID = {}", routerLportTag, routerId);
+ return routerLportTag;
+ } else {
+ LOG.warn("NAT Service : Failed to allocate Router_lPort_Tag from ID Manager for Router ID = {} "
+ + "Continue to use router-id as tunnel-id", routerId);
+ return routerId;
+ }
+ }
+ return routerId;
+ }
+
+ static long getL3Vni(DataBroker broker, String rd) {
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpData(broker, rd);
+ if (vpnInstanceOpDataEntry != null && vpnInstanceOpDataEntry.getL3vni() != null) {
+ return vpnInstanceOpDataEntry.getL3vni();
+ }
+ return NatConstants.DEFAULT_L3VNI_VALUE;
+ }
+
+ private static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = NatUtil.getVpnInstanceOpDataIdentifier(rd);
+ Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (vpnInstanceOpData.isPresent()) {
+ return vpnInstanceOpData.get();
+ }
+ return null;
+ }
+
+ private static boolean isL3VpnOverVxLan(Long l3Vni) {
+ return (l3Vni != null && l3Vni != 0);
+ }
+}
}
rtrList.add(routerId);
builder.setRouterIds(rtrList);
- if (providerNwType != ProviderTypes.GRE) {
+ if (NeutronvpnUtils.isFlatOrVlanNetwork(input)) {
builder.setVpnid(extNetId);
}