import com.google.common.util.concurrent.FutureCallback;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-
import java.math.BigInteger;
import java.util.List;
leaf elantag {type uint32;}
}
+ augment "/odl-fib:fibEntries/odl-fib:vrfTables/odl-fib:vrfEntry" {
+ ext:augment-identifier "routerInterface";
+ leaf uuid {type string;}
+ leaf mac-address {type string;}
+ leaf ip-address {type string;}
+ }
+
container fibEntries {
config true;
list vrfTables{
leaf parent-vpn-rd { type string; }
}
}
-}
\ No newline at end of file
+}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
public class FibManagerImpl implements IFibManager {
private static final Logger LOG = LoggerFactory.getLogger(FibManagerImpl.class);
private final NexthopManager nexthopManager;
public boolean isVPNConfigured() {
return this.vpnmanager.isVPNConfigured();
}
+
}
import org.opendaylight.genius.mdsalutil.MetaDataUtil;
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
import org.opendaylight.genius.utils.ServiceIndex;
import org.opendaylight.genius.utils.batching.ActionableResource;
import org.opendaylight.genius.utils.batching.ActionableResourceImpl;
import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
}
return;
}
+ // ping responder for router interfaces
+ if (installRouterFibEntries(vrfEntry, vpnToDpnList, vpnId, NwConstants.ADD_FLOW)) {
+ return;
+ }
if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.INTERVPN) {
// When it is a leaked route, the LFIB and FIB goes a bit different.
}
return;
}
+ if (installRouterFibEntries(vrfEntry, vpnToDpnList, vpnInstance.getVpnId(), NwConstants.DEL_FLOW)) {
+ return;
+ }
final List<BigInteger> localDpnIdList = deleteLocalFibEntry(vpnInstance.getVpnId(),
vrfTableKey.getRouteDistinguisher(), vrfEntry);
installSubnetRouteInFib(dpnId, elanTag, rd, vpnId, vrfEntry, tx);
continue;
}
+ RouterInterface routerInt = vrfEntry.getAugmentation(RouterInterface.class);
+ if (routerInt != null) {
+ LOG.trace( "Router augmented vrfentry found rd:{}, uuid:{}, ip:{}, mac:{}",
+ rd, routerInt.getUuid(), routerInt.getIpAddress(), routerInt.getMacAddress());
+ installRouterFibEntry(vrfEntry, dpnId, vpnId, routerInt.getUuid(), routerInt.getIpAddress(),
+ new MacAddress(routerInt.getMacAddress()), NwConstants.ADD_FLOW);
+ continue;
+ }
if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) { //Handle local flow creation for imports
LabelRouteInfo lri = getLabelRouteInfo(vrfEntry.getLabel());
if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
vrfEntry.getDestPrefix());
continue;
}
+ // ping responder for router interfaces
+ RouterInterface routerInt = vrfEntry.getAugmentation(RouterInterface.class);
+ if (routerInt != null) {
+ LOG.trace("Router augmented vrfentry found for rd:{}, uuid:{}, ip:{}, mac:{}",
+ rd, routerInt.getUuid(), routerInt.getIpAddress(), routerInt.getMacAddress());
+ installRouterFibEntry(vrfEntry, dpnId, vpnId, routerInt.getUuid(), routerInt.getIpAddress(),
+ new MacAddress(routerInt.getMacAddress()), NwConstants.DEL_FLOW);
+ continue;
+ }
// Passing null as we don't know the dpn
// to which prefix is attached at this point
deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry, tx);
child(VrfEntry.class, new VrfEntryKey(ipPrefix)).build();
return vrfEntryId;
}
+
+ protected Boolean installRouterFibEntries(final VrfEntry vrfEntry, final Collection<VpnToDpnList> vpnToDpnList,
+ long vpnId, int addOrRemove) {
+ RouterInterface routerInt = vrfEntry.getAugmentation(RouterInterface.class);
+ if (routerInt != null && vpnToDpnList != null) {
+ String routerId = routerInt.getUuid();
+ String macAddress = routerInt.getMacAddress();
+ String ipValue = routerInt.getIpAddress();
+ LOG.trace("createFibEntries - Router augmented vrfentry found for for router uuid:{}, ip:{}, mac:{}",
+ routerId, ipValue, macAddress);
+ for (VpnToDpnList vpnDpn : vpnToDpnList) {
+ if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ installRouterFibEntry(vrfEntry, vpnDpn.getDpnId(), vpnId, routerId, ipValue,
+ new MacAddress(macAddress), addOrRemove);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void installRouterFibEntry(final VrfEntry vrfEntry, BigInteger dpnId, long vpnId, String routerUuid,
+ String routerInternalIp, MacAddress routerMac, int addOrRemove) {
+ String[] subSplit = routerInternalIp.split("/");
+
+ String addRemoveStr = (addOrRemove == NwConstants.ADD_FLOW) ? "ADD_FLOW" : "DELETE_FLOW";
+ LOG.trace("{}: bulding Echo Flow entity for dpid:{}, router_ip:{}, vpnId:{}, subSplit:{} ", addRemoveStr,
+ dpnId, routerInternalIp, vpnId, subSplit[0]);
+
+ List<MatchInfo> matches = new ArrayList<>();
+
+ matches.add(new MatchInfo(MatchFieldType.ip_proto, new long[] { IPProtocols.ICMP.intValue() }));
+ matches.add(new MatchInfo(MatchFieldType.metadata,
+ new BigInteger[] { MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+ matches.add(new MatchInfo(MatchFieldType.icmp_v4, new long[] { (short) 8, (short) 0 }));
+ matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_IPV4 }));
+ matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] { subSplit[0], "32" }));
+
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+
+ // Set Eth Src and Eth Dst
+ actionsInfos.add(new ActionInfo(ActionType.move_src_dst_eth, new String[] {}));
+ actionsInfos.add(new ActionInfo(ActionType.set_field_eth_src, new String[] { routerMac.getValue() }));
+
+ // Move Ip Src to Ip Dst
+ actionsInfos.add(new ActionInfo(ActionType.move_src_dst_ip, new String[] {}));
+ actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[] { subSplit[0], "32" }));
+
+ // Set the ICMP type to 0 (echo reply)
+ actionsInfos.add(new ActionInfo(ActionType.set_icmp_type, new String[] { "0" }));
+
+ actionsInfos.add(new ActionInfo(ActionType.nx_load_in_port, new BigInteger[]{ BigInteger.ZERO }));
+
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit,
+ new String[] { Short.toString(NwConstants.L3_FIB_TABLE) }));
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ int priority = FibConstants.DEFAULT_FIB_FLOW_PRIORITY;
+ String flowRef = getFlowRef(dpnId, NwConstants.L3_FIB_TABLE, vrfEntry.getLabel(), priority);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_FIB_TABLE, flowRef, priority, flowRef,
+ 0, 0, NwConstants.COOKIE_VM_FIB_TABLE, matches, instructions);
+
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ mdsalManager.installFlow(flowEntity);
+ } else {
+ mdsalManager.removeFlow(flowEntity);
+ }
+ }
}
LOG.trace("NeutronPortChangeListener Add Subnet Gateway IP {} MAC {} Interface {} VPN {}",
portIP.getIpAddress().getIpv4Address(),routerPort.getMacAddress(),
routerPort.getUuid().getValue(), vpnId.getValue());
- NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, routerPort
- .getUuid().getValue(), routerPort.getMacAddress().getValue(), true, true, false);
+ // ping responder for router interfaces
+ nvpnManager.createVpnInterface(vpnId, routerId, routerPort, null);
+
} else {
LOG.info("Skip router port {} with the following address {}",
routerPort.getUuid().getValue(), portIP.getIpAddress().getIpv6Address());
nvpnNatManager.handleSubnetsForExternalRouter(routerId, dataBroker);
String ipValue = portIP.getIpAddress().getIpv4Address().getValue();
NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue);
+ // ping responder for router interfaces
+ nvpnManager.deleteVpnInterface(vpnId, routerId, routerPort, null);
} else {
LOG.info("Skip router port {} with the following address {}",
routerPort.getUuid().getValue(), portIP.getIpAddress().getIpv6Address());
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.netvirt.elanmanager.api.IElanService;
+import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
}
}
- protected void createVpnInterface(Uuid vpnId, Uuid routerId, Port port, WriteTransaction wrtConfigTxn) {
+ protected void createVpnInterface(Uuid vpnId, Uuid routerId, Port port,
+ WriteTransaction wrtConfigTxn) {
String infName = port.getUuid().getValue();
List<Adjacency> adjList = new ArrayList<>();
List<FixedIps> ips = port.getFixedIps();
-
+ Boolean isRouterInterface = false;
+ if (port.getDeviceOwner() != null) {
+ isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
+ }
+ LOG.trace("createVpnInterface - isRouterInterface:{}", isRouterInterface);
Router rtr = null;
if (routerId != null) {
rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
}
String ipValue = ip.getIpAddress().getIpv4Address().getValue();
NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
- .getMacAddress().getValue(), false, true, false);
+ .getMacAddress().getValue(), isRouterInterface, true, false);
}
// create vpn-interface on this neutron port
Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
- writeVpnInterfaceToDs(vpnId, infName, adjs, wrtConfigTxn);
+ writeVpnInterfaceToDs(vpnId, infName, adjs, isRouterInterface, wrtConfigTxn);
if (routerId != null) {
addToNeutronRouterInterfacesMap(routerId, infName);
}
}
private void createExternalVpnInterface(Uuid vpnId, String infName) {
- writeVpnInterfaceToDs(vpnId, infName, null, null);
+ writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, null);
}
private void writeVpnInterfaceToDs(Uuid vpnId, String infName, Adjacencies adjacencies,
- WriteTransaction wrtConfigTxn) {
+ Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
if (vpnId == null || infName == null) {
LOG.debug("vpn id or interface is null");
return;
}
InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
- VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName)).setName(infName)
- .setVpnInstanceName(vpnId.getValue());
+ VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
+ .setName(infName)
+ .setVpnInstanceName(vpnId.getValue())
+ .setIsRouterInterface(isRouterInterface);
if (adjacencies != null) {
vpnb.addAugmentation(Adjacencies.class, adjacencies);
}
leaf scheduled-for-remove {
type boolean;
}
+ leaf is-router-interface {
+ type boolean;
+ }
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterfaceBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", interfaceName, e);
return;
}
+ } else if (vpnInterface.isIsRouterInterface()) {
+ createVpnInterfaceForRouter(vpnInterface, interfaceName);
+
} else {
LOG.error("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
}
}
});
- }else{
- LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
+ } else if (vpnInterface.isIsRouterInterface()) {
+
+ List<Adjacency> adjsList = new ArrayList<>();
+ Adjacencies adjs = vpnInterface.getAugmentation(Adjacencies.class);
+ if (adjs != null) {
+ adjsList = adjs.getAdjacency();
+ for (Adjacency adj : adjsList) {
+ if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
+ String primaryInterfaceIp = adj.getIpAddress();
+ String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
+ fibManager.removeFibEntry(dataBroker, vpnInterface.getVpnInstanceName(), prefix, null);
+ return;
+ }
+ }
+ }
+ } else {
+ LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event",
+ interfaceName);
}
}
}
}
}
+
+ protected void createVpnInterfaceForRouter(VpnInterface vpnInterface, String interfaceName) {
+ if (vpnInterface == null) {
+ return;
+ }
+ String vpnName = vpnInterface.getVpnInstanceName();
+ String rd = getRouteDistinguisher(vpnName);
+ List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
+ if (adjs == null) {
+ LOG.info("VPN Interface {} of router addition failed as adjacencies for "
+ + "this vpn interface could not be obtained", interfaceName);
+ return;
+ }
+ if (rd == null || rd.isEmpty()) {
+ rd = vpnName;
+ }
+ for (Adjacency adj : adjs) {
+ if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
+ String primaryInterfaceIp = adj.getIpAddress();
+ String macAddress = adj.getMacAddress();
+ String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
+
+ long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey((rd == null) ? vpnName : rd, prefix));
+
+ RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
+ .setMacAddress(macAddress).setIpAddress(primaryInterfaceIp).build();
+
+ VrfEntry vrfEntry = new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
+ .setNextHopAddressList(Arrays.asList(primaryInterfaceIp)).setLabel(label)
+ .setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
+ .addAugmentation(RouterInterface.class, routerInt).build();
+
+ List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
+ InstanceIdentifierBuilder<VrfTables> idBuilder = InstanceIdentifier.builder(FibEntries.class)
+ .child(VrfTables.class, new VrfTablesKey(rd));
+
+ InstanceIdentifier<VrfEntry> vrfEntryId = InstanceIdentifier.builder(FibEntries.class)
+ .child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix))
+ .build();
+ VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
+ return;
+ }
+ }
+ LOG.trace("VPN Interface {} of router addition failed as primary adjacency for"
+ + " this vpn interface could not be obtained", interfaceName);
+ }
}