Setup SMAC on routed packets destined to virtual endpoints 73/50373/21
authorkarthik.prasad <karthik.p@altencalsoftlabs.com>
Thu, 12 Jan 2017 15:27:25 +0000 (20:57 +0530)
committerSam Hague <shague@redhat.com>
Mon, 6 Feb 2017 23:59:41 +0000 (23:59 +0000)
All L3 Routed packets destined to virtual endpoints in the datacenter
managed by ODL do not carry a proper source-mac address in such frames
put out to virtual endpoints. With the fix all the packets destined to
virtual endpoints shall have gateway mac as source mac. If gateway mac
is not recoverable for the subnet on which the virtual endpoint resides,
then the connected mac address of that virtual endpoint will be used as
the source mac address.  Here the connected mac address represents the
mac-address on the tapxxx (or) the vhuxxx port on OVS Datapath for that
virtual endpoint.

Use VrfEntry yang model to represent the source mac.

Sample Group Entry:
group_id=150001,type=all,bucket=actions=set_field:fa:16:3e:a1:4b:61->eth_src,set_field:fa:16:3e:21:b8:d3->eth_dst,load:0x300->NXM_NX_REG6[],resubmit(,220)

Spec Reference link:
https://git.opendaylight.org/gerrit/#/c/49807

Change-Id: I2e75215fd75f051135d702ab63cb792b6cf4cb55
Signed-off-by: karthik.prasad <karthik.p@altencalsoftlabs.com>
Signed-off-by: Achuth Maniyedath <achuth.m@altencalsoftlabs.com>
vpnservice/fibmanager/fibmanager-api/src/main/java/org/opendaylight/netvirt/fibmanager/api/IFibManager.java
vpnservice/fibmanager/fibmanager-api/src/main/yang/odl-fib.yang
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManagerImpl.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibUtil.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/NexthopManager.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkUtil.java

index 418163b1c316146eb3393b70daa951ff76b7b11e..989e26332e539c774885009cd82933a7158f9c1b 100644 (file)
@@ -62,7 +62,7 @@ public interface IFibManager {
                                 String destTepIp);
 
     void addOrUpdateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
-                             int label, RouteOrigin origin, WriteTransaction writeConfigTxn);
+                             int label, String gwMacAddress, RouteOrigin origin, WriteTransaction writeConfigTxn);
 
     void addFibEntryForRouterInterface(DataBroker broker, String rd, String prefix,
                                        RouterInterface routerInterface, long label, WriteTransaction writeConfigTxn);
@@ -73,7 +73,7 @@ public interface IFibManager {
     void removeFibEntry(DataBroker broker, String rd, String prefix, WriteTransaction writeConfigTxn);
 
     void updateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
-                        WriteTransaction writeConfigTxn);
+                        String gwMacAddress, WriteTransaction writeConfigTxn);
 
     void addVrfTable(DataBroker broker, String rd, WriteTransaction writeConfigTxn);
 
index b8860299750e2bce2138d17207403e15a21349b2..5d874ef78dd02cbf65855d96ddbb1f0d427dc7d3 100644 (file)
@@ -59,7 +59,6 @@ module odl-fib {
             leaf gateway_mac_address {
                type string;
             }
-
         }
     }
 
index e83db85878d5bac0cb0bcf572089336ab460b7d7..47b58678213e0bf57389cfb2bbe667564931cada 100755 (executable)
@@ -148,8 +148,9 @@ public class FibManagerImpl implements IFibManager {
 
     @Override
     public void addOrUpdateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
-                                    int label, RouteOrigin origin, WriteTransaction writeConfigTxn) {
-        FibUtil.addOrUpdateFibEntry(broker, rd, prefix, nextHopList, label, origin, writeConfigTxn);
+                                    int label, String gwMacAddress, RouteOrigin origin,
+                                    WriteTransaction writeConfigTxn) {
+        FibUtil.addOrUpdateFibEntry(broker, rd, prefix, nextHopList, label, gwMacAddress, origin, writeConfigTxn);
     }
 
     @Override
@@ -171,8 +172,8 @@ public class FibManagerImpl implements IFibManager {
     }
 
     public void updateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
-                               WriteTransaction writeConfigTxn) {
-        FibUtil.updateFibEntry(broker, rd, prefix, nextHopList, writeConfigTxn);
+                               String gwMacAddress, WriteTransaction writeConfigTxn) {
+        FibUtil.updateFibEntry(broker, rd, prefix, nextHopList, gwMacAddress, writeConfigTxn);
     }
 
     @Override
index 02c5c3adf969ed4c7203aacfc37ce3556981ee38..484923c75fcda5c695f2a25ded2630acfcb67d64 100644 (file)
@@ -474,7 +474,8 @@ public class FibUtil {
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     public static void addOrUpdateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
-                                           int label, RouteOrigin origin, WriteTransaction writeConfigTxn) {
+                                           int label, String gwMacAddress, RouteOrigin origin,
+                                           WriteTransaction writeConfigTxn) {
         if (rd == null || rd.isEmpty()) {
             LOG.error("Prefix {} not associated with vpn", prefix);
             return;
@@ -491,7 +492,7 @@ public class FibUtil {
 
             if (!entry.isPresent()) {
                 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(nextHopList)
-                    .setLabel((long) label).setOrigin(origin.getValue()).build();
+                    .setLabel((long) label).setGatewayMacAddress(gwMacAddress).setOrigin(origin.getValue()).build();
 
                 if (writeConfigTxn != null) {
                     writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
@@ -507,7 +508,7 @@ public class FibUtil {
                     }
                 }
                 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(nh)
-                    .setLabel((long) label).setOrigin(origin.getValue()).build();
+                    .setLabel((long) label).setGatewayMacAddress(gwMacAddress).setOrigin(origin.getValue()).build();
 
                 if (writeConfigTxn != null) {
                     writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
@@ -632,7 +633,7 @@ public class FibUtil {
     }
 
     public static void updateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
-                                      WriteTransaction writeConfigTxn) {
+                                      String gwMacAddress, WriteTransaction writeConfigTxn) {
 
         LOG.debug("Updating fib entry for prefix {} with nextHopList {} for rd {}", prefix, nextHopList, rd);
 
@@ -646,7 +647,7 @@ public class FibUtil {
             // Update the VRF entry with nextHopList
             VrfEntry vrfEntry =
                 new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nextHopList)
-                    .setKey(new VrfEntryKey(prefix)).build();
+                    .setGatewayMacAddress(gwMacAddress).setKey(new VrfEntryKey(prefix)).build();
             if (nextHopList.isEmpty()) {
                 if (writeConfigTxn != null) {
                     writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
index a1f13b0d90c8e4381adfbb5af21c2f5082b5192a..29b2dc572af1bd67dd42ec1dff0261db22abc48d 100644 (file)
@@ -31,6 +31,7 @@ import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
 import org.opendaylight.genius.mdsalutil.actions.ActionPushVlan;
 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldVlanVid;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
@@ -102,10 +103,6 @@ public class NexthopManager implements AutoCloseable {
     private final ItmRpcService itmManager;
     private final IdManagerService idManager;
     private final IElanService elanService;
-    private static final short LPORT_INGRESS_TABLE = 0;
-    private static final short LFIB_TABLE = 20;
-    private static final short FIB_TABLE = 21;
-    private static final short DEFAULT_FLOW_PRIORITY = 10;
     private static final String NEXTHOP_ID_POOL_NAME = "nextHopPointerPool";
     private static final long FIXED_DELAY_IN_MILLISECONDS = 4000;
     private L3VPNTransportTypes configuredTransportTypeL3VPN = L3VPNTransportTypes.Invalid;
@@ -217,8 +214,8 @@ public class NexthopManager implements AutoCloseable {
         }
     }
 
-    protected List<ActionInfo> getEgressActionsForInterface(String ifName) {
-        List<ActionInfo> listActionInfo = new ArrayList<>();
+    protected List<ActionInfo> getEgressActionsForInterface(final String ifName, int actionKey) {
+        List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
         try {
             Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
                 interfaceManager.getEgressActionsForInterface(
@@ -231,26 +228,27 @@ public class NexthopManager implements AutoCloseable {
                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions =
                     rpcResult.getResult().getAction();
                 for (Action action : actions) {
+                    actionKey = action.getKey().getOrder() + (actionKey++);
                     org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action
                         actionClass = action.getAction();
                     if (actionClass instanceof OutputActionCase) {
-                        listActionInfo.add(new ActionOutput(
+                        listActionInfo.add(new ActionOutput(actionKey,
                             ((OutputActionCase) actionClass).getOutputAction().getOutputNodeConnector()));
                     } else if (actionClass instanceof PushVlanActionCase) {
-                        listActionInfo.add(new ActionPushVlan());
+                        listActionInfo.add(new ActionPushVlan(actionKey));
                     } else if (actionClass instanceof SetFieldCase) {
                         if (((SetFieldCase) actionClass).getSetField().getVlanMatch() != null) {
                             int vlanVid = ((SetFieldCase) actionClass).getSetField().getVlanMatch()
                                 .getVlanId().getVlanId().getValue();
-                            listActionInfo.add(new ActionSetFieldVlanVid(vlanVid));
+                            listActionInfo.add(new ActionSetFieldVlanVid(actionKey, vlanVid));
                         }
                     } else if (actionClass instanceof NxActionResubmitRpcAddGroupCase) {
                         Short tableId = ((NxActionResubmitRpcAddGroupCase) actionClass).getNxResubmit().getTable();
-                        listActionInfo.add(new ActionNxResubmit(action.getKey().getOrder() + 1, tableId));
+                        listActionInfo.add(new ActionNxResubmit(actionKey, tableId));
                     } else if (actionClass instanceof NxActionRegLoadNodesNodeTableFlowApplyActionsCase) {
                         NxRegLoad nxRegLoad =
                             ((NxActionRegLoadNodesNodeTableFlowApplyActionsCase) actionClass).getNxRegLoad();
-                        listActionInfo.add(new ActionRegLoad(action.getKey().getOrder() + 1, NxmNxReg6.class,
+                        listActionInfo.add(new ActionRegLoad(actionKey, NxmNxReg6.class,
                             nxRegLoad.getDst().getStart(), nxRegLoad.getDst().getEnd(),
                             nxRegLoad.getValue().longValue()));
                     }
@@ -305,8 +303,8 @@ public class NexthopManager implements AutoCloseable {
         return null;
     }
 
-    public long createLocalNextHop(long vpnId, BigInteger dpnId,
-                                   String ifName, String ipNextHopAddress, String ipPrefixAddress) {
+    public long createLocalNextHop(long vpnId, BigInteger dpnId, String ifName,
+                                   String ipNextHopAddress, String ipPrefixAddress, String gwMacAddress) {
         String macAddress = FibUtil.getMacAddressFromPrefix(dataBroker, ifName, ipPrefixAddress);
         String ipAddress = (macAddress != null) ? ipPrefixAddress : ipNextHopAddress;
 
@@ -326,16 +324,22 @@ public class NexthopManager implements AutoCloseable {
                 }
                 List<BucketInfo> listBucketInfo = new ArrayList<>();
                 List<ActionInfo> listActionInfo = new ArrayList<>();
+                int actionKey = 0;
                 // MAC re-write
                 if (macAddress != null) {
-                    int actionKey = listActionInfo.size();
-                    listActionInfo.add(new ActionSetFieldEthernetDestination(actionKey, new MacAddress(macAddress)));
-                    //listActionInfo.add(0, new ActionPopMpls());
+                    if (gwMacAddress != null) {
+                        LOG.trace("The Local NextHop Group Source Mac {} for VpnInterface {} on VPN {}",
+                                gwMacAddress, ifName, vpnId);
+                        listActionInfo.add(
+                                new ActionSetFieldEthernetSource(actionKey++, new MacAddress(gwMacAddress)));
+                    }
+                    listActionInfo.add(new ActionSetFieldEthernetDestination(actionKey++, new MacAddress(macAddress)));
+                    // listActionInfo.add(0, new ActionPopMpls());
                 } else {
                     //FIXME: Log message here.
                     LOG.debug("mac address for new local nexthop is null");
                 }
-                listActionInfo.addAll(getEgressActionsForInterface(ifName));
+                listActionInfo.addAll(getEgressActionsForInterface(ifName, actionKey));
                 BucketInfo bucket = new BucketInfo(listActionInfo);
 
                 listBucketInfo.add(bucket);
index 8834c2473c15a9a159ed78167fbc2492fee4d9b6..48d742d0b797f906bce1fa2de8fdffb9be947eda 100755 (executable)
@@ -869,7 +869,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             }
 
             final long groupId = nextHopManager.createLocalNextHop(parentVpnId, dpnId,
-                localNextHopInfo.getVpnInterfaceName(), localNextHopIP, vrfEntry.getDestPrefix());
+                    localNextHopInfo.getVpnInterfaceName(), localNextHopIP, vrfEntry.getDestPrefix(),
+                    vrfEntry.getGatewayMacAddress());
             if (groupId == 0) {
                 LOG.error("Unable to create Group for local prefix {} on rd {} for vpninterface {} on Node {}",
                     vrfEntry.getDestPrefix(), rd, localNextHopInfo.getVpnInterfaceName(), dpnId.toString());
@@ -1154,7 +1155,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             } else {
                 addRewriteDstMacAction(vpnId, vrfEntry, actionInfos);
             }
-            List<ActionInfo> egressActions = nextHopManager.getEgressActionsForInterface(egressInterface);
+            List<ActionInfo> egressActions = nextHopManager.getEgressActionsForInterface(egressInterface,
+                    actionInfos.size());
             if (egressActions.isEmpty()) {
                 LOG.error("Failed to retrieve egress action for prefix {} nextHop {} interface {}. "
                     + "Aborting remote FIB entry creation.",
index d167eda578dbf24807b5b1d290bded5f56731adc..2dba95fe9459126a0ce4b35116ad399a641a0610 100644 (file)
@@ -758,7 +758,7 @@ public class NatUtil {
                 return;
             }
             fibManager.addOrUpdateFibEntry(broker, rd, prefix, Collections.singletonList(nextHopIp), (int) label,
-                    origin, null);
+                    null /*gatewayMacAddress*/, origin, null /*writeTxn*/);
             bgpManager.advertisePrefix(rd, prefix, Collections.singletonList(nextHopIp), (int) label);
             LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
         } catch (Exception e) {
index 6657c9b01f90adb4c2f868f1792273b54347a7bd..9914e74d5e11c3542502db4c89536761e4be616b 100755 (executable)
@@ -570,7 +570,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         }
 
         List<VpnInstanceOpDataEntry> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
-
+        Optional<String> gwMac = Optional.absent();
         LOG.trace("NextHops for interface {} are {}", interfaceName, nextHops);
         for (Adjacency nextHop : nextHops) {
             String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
@@ -599,7 +599,10 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 final Uuid subnetId = nextHop.getSubnetId();
                 setupGwMacIfRequired(dpnId, vpnName, interfaceName, vpnId, subnetId,
                         writeInvTxn, NwConstants.ADD_FLOW);
-                addArpResponderFlow(dpnId, lportTag, vpnName, vpnId, interfaceName, subnetId, writeInvTxn);
+                final Optional<String> gatewayIp = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
+                gwMac = getGatewayMacAddressForInterface(vpnName, interfaceName, gatewayIp.get());
+                addArpResponderFlow(dpnId, lportTag, vpnName, vpnId, interfaceName, subnetId,
+                        gwMac.get(), gatewayIp.get(), writeInvTxn);
             } else {
                 //Extra route adjacency
                 LOG.trace("Adding prefix {} and nextHopList {} as extra-route for vpn", nextHop.getIpAddress(),
@@ -621,7 +624,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             if (rd != null) {
                 addToLabelMapper(label, dpnId, nextHop.getIpAddress(), nhList, vpnId,
                     interfaceName, null, false, rd, writeOperTxn);
-                addPrefixToBGP(rd, nextHop.getIpAddress(), nhList, label, RouteOrigin.LOCAL, writeConfigTxn);
+                addPrefixToBGP(rd, nextHop.getIpAddress(), nhList, label, gwMac.isPresent() ? gwMac.get() : null,
+                    RouteOrigin.LOCAL, writeConfigTxn);
                 //TODO: ERT - check for VPNs importing my route
                 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
                     String vpnRd = vpn.getVrfId();
@@ -629,14 +633,14 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         LOG.debug("Exporting route with rd {} prefix {} nexthop {} label {} to VPN {}", vpnRd,
                             nextHop.getIpAddress(), nextHopIp, label, vpn);
                         fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, nextHop.getIpAddress(), nhList, (int) label,
-                            RouteOrigin.SELF_IMPORTED, writeConfigTxn);
+                            gwMac.isPresent() ? gwMac.get() : null, RouteOrigin.SELF_IMPORTED, writeConfigTxn);
                     }
                 }
             } else {
                 // ### add FIB route directly
                 fibManager.addOrUpdateFibEntry(dataBroker, vpnName, nextHop.getIpAddress(),
                         (nextHopIp == null ? Collections.emptyList() : Collections.singletonList(nextHopIp)),
-                        (int) label, RouteOrigin.LOCAL, writeConfigTxn);
+                        (int) label, gwMac.isPresent() ? gwMac.get() : null, RouteOrigin.LOCAL, writeConfigTxn);
             }
         }
     }
@@ -702,9 +706,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     LOG.info("Updating label mapper : label {} dpn {} prefix {} nexthoplist {} vpnid {} rd {}", label,
                         srcDpnId, prefix, nhList, vpnId, rd);
                     updateLabelMapper(label, nhList);
-
+                    Optional<String> gwMacAddr = getGatewayMacAddressForInterface(vpnInterface.getVpnInstanceName(),
+                            vpnInterface.getName(),prefix);
                     // Update the VRF entry with nextHop
-                    fibManager.updateFibEntry(dataBroker, rd, prefix, nhList, null);
+                    fibManager.updateFibEntry(dataBroker, rd, prefix, nhList,
+                        gwMacAddr.isPresent() ? gwMacAddr.get() : null, null);
 
                     //Get the list of VPN's importing this route(prefix) .
                     // Then update the VRF entry with nhList
@@ -715,7 +721,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         if (vpnRd != null) {
                             LOG.debug("Exporting route with rd {} prefix {} nhList {} label {} to VPN {}", vpnRd,
                                 prefix, nhList, label, vpn);
-                            fibManager.updateFibEntry(dataBroker, vpnRd, prefix, nhList, null);
+                            fibManager.updateFibEntry(dataBroker, vpnRd, prefix, nhList,
+                                gwMacAddr.isPresent() ? gwMacAddr.get() : null, null);
                         }
                     }
                     // Advertise the prefix to BGP only for external vpn
@@ -760,6 +767,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     // If nextHopList is already cleaned , no need to modify again
                     if ((nextHopList != null) & (!nextHopList.isEmpty())) {
                         isNextHopRemoveReqd = true;
+
                         value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
                         Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
 
@@ -776,9 +784,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     LOG.info("Updating label mapper : label {} dpn {} prefix {} nexthoplist {} vpnid {} rd {}", label,
                         srcDpnId, prefix, nhList, vpnId, rd);
                     updateLabelMapper(label, nhList);
-
+                    Optional<String> gwMacAddr = getGatewayMacAddressForInterface(vpnInterface.getVpnInstanceName(),
+                        vpnInterface.getName(),prefix);
                     // Update the VRF entry with emtpy nextHop
-                    fibManager.updateFibEntry(dataBroker, rd, prefix, new ArrayList<>() /* empty */, null);
+                    fibManager.updateFibEntry(dataBroker, rd, prefix, new ArrayList<>()/* empty */,
+                            gwMacAddr.isPresent() ? gwMacAddr.get() : null, null);
 
                     //Get the list of VPN's importing this route(prefix) .
                     // Then update the VRF entry with nhList
@@ -789,7 +799,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         if (vpnRd != null) {
                             LOG.debug("Exporting route with rd {} prefix {} nhList {} label {} to VPN {}", vpnRd,
                                 prefix, nhList, label, vpn);
-                            fibManager.updateFibEntry(dataBroker, vpnRd, prefix, nhList, null);
+                            fibManager.updateFibEntry(dataBroker, vpnRd, prefix, nhList,
+                                gwMacAddr.isPresent() ? gwMacAddr.get() : null, null);
                         }
                     }
 
@@ -929,6 +940,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         String prefix = vrfEntry.getDestPrefix();
                         long label = vrfEntry.getLabel();
                         List<String> nextHops = vrfEntry.getNextHopAddressList();
+                        String gwMac = vrfEntry.getGatewayMacAddress();
                         SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
                         for (String nh : nextHops) {
                             if (route != null) {
@@ -937,11 +949,10 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                     vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
                                 importSubnetRouteForNewVpn(vpnRd, prefix, nh, (int) label, route, writeConfigTxn);
                             } else {
-                                LOG.info("Importing fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd,
-                                    prefix, nh, label, vpn.getVpnInstanceName());
+                                LOG.info("Importing fib entry rd {} prefix {} nexthop {} label {} gwmac {} "
+                                        + "to vpn {}", vpnRd, prefix, nh, label, gwMac, vpn.getVpnInstanceName());
                                 fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, prefix, Collections.singletonList(nh),
-                                    (int) label,
-                                    RouteOrigin.SELF_IMPORTED, writeConfigTxn);
+                                    (int) label, gwMac, RouteOrigin.SELF_IMPORTED, writeConfigTxn);
                             }
                         }
                     } catch (Exception e) {
@@ -961,12 +972,15 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
 
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
-    private void addPrefixToBGP(String rd, String prefix, List<String> nextHopList, long label, RouteOrigin origin,
-                                WriteTransaction writeConfigTxn) {
+    private void addPrefixToBGP(String rd, String prefix, List<String> nextHopList, long label, String gwMacAddress,
+                                RouteOrigin origin, WriteTransaction writeConfigTxn) {
         try {
-            LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopList, label);
-            fibManager.addOrUpdateFibEntry(dataBroker, rd, prefix, nextHopList, (int)label, origin, writeConfigTxn);
-            LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopList, label);
+            LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {} gwMac {}",
+                    rd, prefix, nextHopList, label, gwMacAddress);
+            fibManager.addOrUpdateFibEntry(dataBroker, rd, prefix, nextHopList, (int)label,
+                    gwMacAddress, origin, writeConfigTxn);
+            LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {} gwMac {}",
+                    rd, prefix, nextHopList, label, gwMacAddress);
             // Advertize the prefix to BGP only if nexthop ip is available
             if (nextHopList != null && !nextHopList.isEmpty()) {
                 bgpManager.advertisePrefix(rd, prefix, nextHopList, (int)label);
@@ -1179,29 +1193,27 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         }
     }
 
-    private void addArpResponderFlow(final BigInteger dpId, final int lportTag, final String vpnName,
-                                     final long vpnId, final String ifName, final Uuid subnetId,
-                                     final WriteTransaction writeInvTxn) {
+    private  void addArpResponderFlow(final BigInteger dpId, final int lportTag, final String vpnName,
+                                      final long vpnId, final String ifName, final Uuid subnetId,
+                                      final String subnetGwMac, final String gwIp, final WriteTransaction writeInvTxn) {
         LOG.trace("Creating the ARP Responder flow for VPN Interface {}",ifName);
-        final Optional<String> gatewayIp = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
-        if (gatewayIp.isPresent()) {
-            String gwIp = gatewayIp.get();
-            LOG.trace("VPN Interface Adjacency Subnet Gateway IP {}", gwIp);
-            VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, gwIp);
-            //Check if a router gateway interface is available for the subnet gw is so then use Router interface
-            // else use connected interface
-            final String subNetGwMac = (gwPort != null && gwPort.isSubnetIp())
-                ? gwPort.getMacAddress() : InterfaceUtils.getMacAddressForInterface(dataBroker, ifName).get();
-            LOG.debug("VPN Interface Subnet Gateway MAC for {} interface to be used for ARPResponder is {}",
-                    (gwPort != null && gwPort.isSubnetIp()) ? "Router" : "Connected", subNetGwMac);
-            final String flowId = ArpResponderUtil.getFlowID(lportTag, gwIp);
-            List<Action> actions = ArpResponderUtil.getActions(ifaceMgrRpcService, ifName, gwIp, subNetGwMac);
-            ArpResponderUtil.installFlow(mdsalManager, writeInvTxn, dpId, flowId, flowId,
-                    NwConstants.DEFAULT_ARP_FLOW_PRIORITY, ArpResponderUtil.generateCookie(lportTag, gwIp),
-                    ArpResponderUtil.getMatchCriteria(lportTag, vpnId, gwIp),
-                    Collections.singletonList(MDSALUtil.buildApplyActionsInstruction(actions)));
-            LOG.trace("Installed the ARP Responder flow for VPN Interface {}", ifName);
-        }
+        final String flowId = ArpResponderUtil.getFlowID(lportTag, gwIp);
+        List<Action> actions = ArpResponderUtil.getActions(ifaceMgrRpcService, ifName, gwIp, subnetGwMac);
+        ArpResponderUtil.installFlow(mdsalManager, writeInvTxn, dpId, flowId, flowId,
+                NwConstants.DEFAULT_ARP_FLOW_PRIORITY, ArpResponderUtil.generateCookie(lportTag, gwIp),
+                ArpResponderUtil.getMatchCriteria(lportTag, vpnId, gwIp),
+                Collections.singletonList(MDSALUtil.buildApplyActionsInstruction(actions)));
+        LOG.trace("Installed the ARP Responder flow for VPN Interface {}", ifName);
+    }
+
+    private Optional<String> getGatewayMacAddressForInterface(String vpnName, String ifName, String ipAddress) {
+        Optional<String> routerGwMac = Optional.absent();
+        VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipAddress);
+        //Check if a router gateway interface is available for the subnet gw is so then use Router interface
+        // else use connected interface
+        routerGwMac = Optional.of((gwPort != null && gwPort.isSubnetIp())
+                ? gwPort.getMacAddress() : InterfaceUtils.getMacAddressForInterface(dataBroker, ifName).get());
+        return routerGwMac;
     }
 
     private void removeArpResponderFlow(final BigInteger dpId, final int lportTag, final Uuid subnetUuid,
@@ -1711,11 +1723,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 newLabel);
         } else {
             if (rd != null) {
-                addPrefixToBGP(rd, destination, nextHopIpList, label, origin, writeConfigTxn);
+                addPrefixToBGP(rd, destination, nextHopIpList, label, null, origin, writeConfigTxn);
             } else {
                 // ### add FIB route directly
-                fibManager.addOrUpdateFibEntry(dataBroker, routerID, destination, nextHopIpList, label, origin,
-                    writeConfigTxn);
+                fibManager.addOrUpdateFibEntry(dataBroker, routerID, destination, nextHopIpList, label,
+                        null /*gatewayMacAddress*/, origin, writeConfigTxn);
             }
         }
         if (!writeOperTxnPresent) {
index 45f9a27dc65b6a8bb88bcfde30f96c7687813b17..30ac9afc22b1de8589aedb68c8740c071ace34f9 100755 (executable)
@@ -1356,19 +1356,18 @@ public class VpnUtil {
 
     public static void setupGwMacIfExternalVpn(DataBroker dataBroker, IMdsalApiManager mdsalManager, BigInteger dpnId,
             String interfaceName, long vpnId, WriteTransaction writeInvTxn, int addOrRemove) {
-        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn
-                .instance.VpnIds>
-                vpnIdsInstanceIdentifier = getVpnIdToVpnInstanceIdentifier(vpnId);
-        Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds>
-                vpnIdsOptional = read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance
+            .VpnIds> vpnIdsInstanceIdentifier = getVpnIdToVpnInstanceIdentifier(vpnId);
+        Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance
+            .VpnIds> vpnIdsOptional = read(
+                dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
         if (vpnIdsOptional.isPresent() && vpnIdsOptional.get().isExternalVpn()) {
-            Optional<String> gwMacAddressOptional = InterfaceUtils.getMacAddressForInterface(dataBroker, interfaceName);
-            if (!gwMacAddressOptional.isPresent()) {
+            Optional<String> gwMacAddress = InterfaceUtils.getMacAddressForInterface(dataBroker, interfaceName);
+            if (!gwMacAddress.isPresent()) {
                 LOG.error("Failed to get gwMacAddress for interface {}", interfaceName);
                 return;
             }
-            String gwMacAddress = gwMacAddressOptional.get();
-            FlowEntity flowEntity = VpnUtil.buildL3vpnGatewayFlow(dpnId, gwMacAddress, vpnId);
+            FlowEntity flowEntity = VpnUtil.buildL3vpnGatewayFlow(dpnId, gwMacAddress.get(), vpnId);
             if (addOrRemove == NwConstants.ADD_FLOW) {
                 mdsalManager.addFlowToTx(flowEntity, writeInvTxn);
             } else if (addOrRemove == NwConstants.DEL_FLOW) {
@@ -1377,6 +1376,7 @@ public class VpnUtil {
         }
     }
 
+
     public static Optional<VpnPortipToPort> getRouterInterfaceForVpnInterface(DataBroker dataBroker,
                                                                               String interfaceName,
                                                                               String vpnName,
index d80c3596fe06d869e7e4e34cd013d48acb193d8e..f277e4a3aed25df1cd5eba1af36a0b2b8bb68988 100755 (executable)
@@ -514,7 +514,7 @@ public class InterVpnLinkUtil {
         LOG.debug("Writing FibEntry to DS:  vpnRd={}, prefix={}, label={}, nexthop={} (interVpnLink)",
             vpnRd, destination, label, nexthop);
         fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, destination, Collections.singletonList(nexthop), label,
-            RouteOrigin.STATIC, null);
+            null /*gatewayMacAddress*/, RouteOrigin.STATIC, null);
 
         // Now advertise to BGP. The nexthop that must be advertised to BGP are the IPs of the DPN where the
         // VPN's endpoint have been instantiated