import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
-
import org.apache.thrift.TException;
import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
//static IITMProvider itmProvider;
//map<rd, map<prefix/len:nexthop, label>>
private static Map<String, Map<String, Long>> staledFibEntriesMap = new ConcurrentHashMap<>();
+ //map<rd, map<mac, l2vni>>
+ private static Map<String, Map<String, Long>> staledMacEntriesMap = new ConcurrentHashMap<>();
+
+ //map<rd, map<tep-ip, list<mac, l2vni>>>
+ private static Map<String, Map<String, Map<String, Long>>> rt2TepMap = new ConcurrentHashMap<>();
static final String BGP_ENTITY_TYPE_FOR_OWNERSHIP = "bgp";
static final String BGP_ENTITY_NAME = "bgp";
static int totalStaledCount = 0;
static int totalCleared = 0;
static int totalExternalRoutes = 0;
+ static int totalExternalMacRoutes = 0;
private static final Class[] REACTORS = {
ConfigServerReactor.class, AsIdReactor.class,
: label.intValue();
int l3vni = (val.getL3vni() == null) ? qbgpConstants.LBL_NO_LABEL
: val.getL3vni().intValue();
+ int l2vni = (val.getL2vni() == null) ? qbgpConstants.LBL_NO_LABEL
+ : val.getL2vni().intValue();
BgpControlPlaneType protocolType = val.getBgpControlPlaneType();
int ethernetTag = val.getEthtag().intValue();
int afiInt = testValueAFI(pfxlen);
try {
- br.addPrefix(rd, pfxlen, nh, lbl, l3vni, BgpUtil.convertToThriftProtocolType(protocolType),
- ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType),
- routerMac);
+ br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni, BgpUtil.convertToThriftProtocolType(protocolType),
+ ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
} catch (TException | BgpRouterException e) {
LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
}
// TODO: decide correct label here
int label = update.getL3label();
+ int l2label = update.getL2label();
String prefix = update.getPrefix();
int plen = update.getPrefixlen();
// use "rd" to query vrf table and obtain the protocol_type.
// Currently using PROTOCOL_EVPN as default.
onUpdatePushRoute(
- protocol_type.PROTOCOL_EVPN,
- rd,
- prefix,
- plen,
- nexthop,
- update.getEthtag(),
- update.getEsi(),
- update.getMacaddress(),
- label,
- update.getRoutermac(),
- afi
- );
+ protocol_type.PROTOCOL_EVPN,
+ rd,
+ prefix,
+ plen,
+ nexthop,
+ update.getEthtag(),
+ update.getEsi(),
+ update.getMacaddress(),
+ label,
+ l2label,
+ update.getRoutermac(),
+ afi);
}
}
}
}
}
+ public static void addTepToElanDS(String rd, String tepIp, String mac, Long l2vni) {
+ boolean needUpdate = addToRt2TepMap(rd, tepIp, mac, l2vni);
+ if (needUpdate) {
+ LOG.info("Adding tepIp {} with RD {} to ELan DS", tepIp, rd);
+ BgpUtil.addTepToElanInstance(dataBroker, rd, tepIp);
+ } else {
+ LOG.debug("Skipping the Elan update for RT2 from tep {} rd {}", tepIp, rd);
+ }
+ }
+
+ public static void deleteTepfromElanDS(String rd, String tepIp, String mac) {
+ boolean needUpdate = deleteFromRt2TepMap(rd, tepIp, mac);
+ if (needUpdate) {
+ LOG.info("Deleting tepIp {} with RD {} to ELan DS", tepIp, rd);
+ BgpUtil.deleteTepFromElanInstance(dataBroker, rd, tepIp);
+ } else {
+ LOG.debug("Skipping the Elan update for RT2 withdraw from tep {} rd {}", tepIp, rd);
+ }
+ }
+
/* onUpdatePushRoute
* Get Stale fibDSWriter map, and compare current route/fibDSWriter entry.
* - Entry compare shall include NextHop, Label.
String esi,
String macaddress,
int label,
+ int l2label,
String routermac,
af_afi afi)
throws InterruptedException, ExecutionException, TimeoutException {
boolean addroute = false;
+ boolean macupdate = false;
long l3vni = 0L;
VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
encapType = VrfEntry.EncapType.Vxlan;
VpnInstanceOpDataEntry vpnInstanceOpDataEntry = BgpUtil.getVpnInstanceOpData(dataBroker, rd);
if (vpnInstanceOpDataEntry != null) {
- l3vni = vpnInstanceOpDataEntry.getL3vni();
+ if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
+ LOG.info("Got RT2 route for RD {} l3label {} l2label {} from tep {} with mac {} remote RD {}",
+ vpnInstanceOpDataEntry.getVpnInstanceName(), label, l2label, nextHop, macaddress, rd);
+ addTepToElanDS(rd, nextHop, macaddress, (long)l2label);
+ macupdate = true;
+ } else {
+ l3vni = vpnInstanceOpDataEntry.getL3vni();
+ }
} else {
LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
return;
}
}
+
if (!staledFibEntriesMap.isEmpty()) {
// restart Scenario, as MAP is not empty.
Map<String, Long> map = staledFibEntriesMap.get(rd);
LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
addroute = true;
}
- if (addroute) {
+ if (macupdate) {
+ LOG.info("ADD: Adding Mac Fib entry rd {} mac{} nexthop {} l2vni {}", rd, macaddress, nextHop, l2label);
+ fibDSWriter.addMacEntryToDS(rd, macaddress, prefix, Collections.singletonList(nextHop),
+ encapType, l2label, routermac, RouteOrigin.BGP);
+ LOG.info("ADD: Added Mac Fib entry rd {} prefix {} nexthop {} label {}", rd, macaddress, nextHop, l2label);
+ } else if (addroute) {
LOG.info("ADD: Adding Fib entry rd {} prefix {} nexthop {} label {} afi {}",
rd, prefix, nextHop, label, afi);
// TODO: modify addFibEntryToDS signature
}
}
+ public static void onUpdateWithdrawRoute(protocol_type protocolType,
+ String rd,
+ String prefix,
+ int plen,
+ String nextHop,
+ String macaddress)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ long vni = 0L;
+ boolean macupdate = false;
+ if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = BgpUtil.getVpnInstanceOpData(dataBroker, rd);
+ if (vpnInstanceOpDataEntry != null) {
+ vni = vpnInstanceOpDataEntry.getL3vni();
+ if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
+ LOG.debug("Got RT2 withdraw for RD %s from tep %s with mac %s remote RD %s",
+ vpnInstanceOpDataEntry.getVpnInstanceName(), vni, nextHop, macaddress, rd);
+ deleteTepfromElanDS(rd, nextHop, macaddress);
+ LOG.debug("For rd %s. skipping fib update", rd);
+ macupdate = true;
+ }
+ } else {
+ LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
+ return;
+ }
+ }
+ if (macupdate) {
+ LOG.info("Removing Mac Fib entry rd {} mac{} nexthop {} ", rd, macaddress, nextHop);
+ fibDSWriter.removeMacEntryFromDS(rd, macaddress);
+ LOG.info("Removed Mac Fib entry rd {} prefix {} nexthop {} ", rd, macaddress, nextHop);
+ } else {
+ LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
+ fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nextHop);
+ LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
+ }
+ }
+
+ //TODO: below function is for testing purpose with cli
+ public static void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
+ LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
+ fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
+ String vpnName = BgpUtil.getVpnNameFromRd(dataBroker, rd);
+ if (vpnName != null) {
+ vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, 0 /*INVALID_LABEL*/,
+ RouteOrigin.BGP, NwConstants.DEL_FLOW);
+ }
+ }
+
private static boolean isRouteModified(int label, Long labelInStaleMap) {
return labelInStaleMap != null && !labelInStaleMap.equals(Long.valueOf(label));
}
Long label = net.getLabel();
int lbl = (label == null) ? 0 : label.intValue();
int l3vni = (net.getL3vni() == null) ? 0 : net.getL3vni().intValue();
+ int l2vni = (net.getL2vni() == null) ? 0 : net.getL2vni().intValue();
Long afi = net.getAfi();
int afint = (afi == null) ? (int) af_afi.AFI_IP.getValue() : afi.intValue();
if (rd == null && lbl > 0) {
String routerMac = net.getRoutermac();
try {
- br.addPrefix(rd, pfxlen, nh, lbl, l3vni, BgpUtil.convertToThriftProtocolType(protocolType),
- ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType),
- routerMac);
+ br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni,
+ BgpUtil.convertToThriftProtocolType(protocolType),
+ ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
} catch (Exception e) {
LOG.error("Replay:addPfx() received exception", e);
}
*/
public static void deleteExternalFibRoutes() {
totalExternalRoutes = 0;
+ totalExternalMacRoutes = 0;
try {
/*
* at the time FIB route deletion, Wait till all PENDING write transaction
List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
for (VrfTables vrfTable : staleVrfTables) {
rd = vrfTable.getRouteDistinguisher();
- if (vrfTable.getVrfEntry() == null) {
- LOG.error("deleteExternalFibRoutes::getVrfEntry is null");
- continue;
- }
- for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
- if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
- //route cleanup is only meant for the routes learned through BGP.
- continue;
+ if (vrfTable.getVrfEntry() != null) {
+ for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
+ if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
+ //route cleanup is only meant for the routes learned through BGP.
+ continue;
+ }
+ totalExternalRoutes++;
+ fibDSWriter.removeFibEntryFromDS(rd, vrfEntry.getDestPrefix());
+ }
+ } else if (vrfTable.getMacVrfEntry() != null) {
+ for (MacVrfEntry macEntry : vrfTable.getMacVrfEntry()) {
+ if (RouteOrigin.value(macEntry.getOrigin()) != RouteOrigin.BGP) {
+ //route cleanup is only meant for the routes learned through BGP.
+ continue;
+ }
+ totalExternalMacRoutes++;
+ fibDSWriter.removeMacEntryFromDS(rd, macEntry.getMac());
}
- totalExternalRoutes++;
- fibDSWriter.removeFibEntryFromDS(rd, vrfEntry.getDestPrefix());
}
}
} else {
} catch (InterruptedException | ReadFailedException e) {
LOG.error("deleteExternalFibRoutes:: error ", e);
}
- LOG.debug("deleted {} fib entries ", totalExternalRoutes);
+ LOG.debug("deleted {} fib entries {} mac entries", totalExternalRoutes, totalExternalMacRoutes);
}
//map<rd, map<prefix/len:nexthop, label>>
return staledFibEntriesMap;
}
- //TODO: below function is for testing purpose with cli
- public static void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
- LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
- fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
- String vpnName = BgpUtil.getVpnNameFromRd(dataBroker, rd);
- if (vpnName != null) {
- vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, 0 /*INVALID_LABEL*/,
- RouteOrigin.BGP, NwConstants.DEL_FLOW);
+ public static Map<String, Map<String, Long>> getStaledMacEntriesMap() {
+ return staledMacEntriesMap;
+ }
+
+ public static Map<String, Map<String, Map<String, Long>>> getRt2TepMap() {
+ return rt2TepMap;
+ }
+
+ public static boolean addToRt2TepMap(String rd, String tepIp, String mac, Long l2vni) {
+ boolean isFirstMacUpdateFromTep = false;
+ if (getRt2TepMap().containsKey(rd)) {
+ if (getRt2TepMap().get(rd).containsKey(tepIp)) {
+ LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and tep-ip {}. No Elan DS write required",
+ mac, l2vni, rd, tepIp);
+ getRt2TepMap().get(rd).get(tepIp).put(mac, l2vni);
+ } else {
+ LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and new tep-ip {}",
+ mac, rd, tepIp);
+ isFirstMacUpdateFromTep = true;
+ Map<String, Long> macList = new HashMap<>();
+ macList.put(mac, l2vni);
+ getRt2TepMap().get(rd).put(tepIp, macList);
+ }
+ } else {
+ LOG.debug("RT2 with mac {} l2vni {} from new rd {} and tep ip {}",
+ mac, l2vni, rd, tepIp);
+ isFirstMacUpdateFromTep = true;
+ Map<String, Long> macList = new HashMap<>();
+ macList.put(mac, l2vni);
+ Map<String, Map<String, Long>> tepIpMacMap = new HashMap<>();
+ tepIpMacMap.put(tepIp, macList);
+ getRt2TepMap().put(rd, tepIpMacMap);
+ }
+ return isFirstMacUpdateFromTep;
+ }
+
+ public static boolean deleteFromRt2TepMap(String rd, String tepIp, String mac) {
+ boolean isLastMacUpdateFromTep = false;
+ LOG.debug("RT2 withdraw with rd {} mac {} tep-ip {} ", rd, mac, tepIp);
+ if (getRt2TepMap().containsKey(rd)) {
+ if (getRt2TepMap().get(rd).containsKey(tepIp)) {
+ if (getRt2TepMap().get(rd).get(tepIp).containsKey(mac)) {
+ LOG.debug("RT2 Withdraw : Removing the mac {} from Map", mac);
+ getRt2TepMap().get(rd).get(tepIp).remove(mac);
+ if (getRt2TepMap().get(rd).get(tepIp).isEmpty()) {
+ isLastMacUpdateFromTep = true;
+ LOG.debug("RT2 Withdraw : Removing the tep-ip {} from Map", tepIp);
+ getRt2TepMap().get(rd).remove(tepIp);
+ if (getRt2TepMap().get(rd).isEmpty()) {
+ LOG.debug("RT2 Withdraw : Removing the rd {} from Map", rd);
+ getRt2TepMap().remove(rd);
+ }
+ }
+ }
+ }
}
+ return isLastMacUpdateFromTep;
}
public boolean isBgpConnected() {
import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTeps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTepsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTepsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.EvpnRdToNetworks;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.evpn.rd.to.networks.EvpnRdToNetwork;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.evpn.rd.to.networks.EvpnRdToNetworkKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
import org.opendaylight.yangtools.yang.binding.DataObject;
ExecutionException, TimeoutException {
InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = MDSALUtil.read(broker,
- LogicalDatastoreType.OPERATIONAL, id);
+ LogicalDatastoreType.CONFIGURATION, id);
if (vpnInstanceOpData.isPresent()) {
return vpnInstanceOpData.get();
}
.child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
}
+ static String getElanNamefromRd(DataBroker broker, String rd) {
+ InstanceIdentifier<EvpnRdToNetwork> id = getEvpnRdToNetworkIdentifier(rd);
+ Optional<EvpnRdToNetwork> evpnRdToNetworkOpData = MDSALUtil.read(broker,
+ LogicalDatastoreType.OPERATIONAL, id);
+ if (evpnRdToNetworkOpData.isPresent()) {
+ return evpnRdToNetworkOpData.get().getNetworkId();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<EvpnRdToNetwork> getEvpnRdToNetworkIdentifier(String rd) {
+ return InstanceIdentifier.builder(EvpnRdToNetworks.class)
+ .child(EvpnRdToNetwork.class, new EvpnRdToNetworkKey(rd)).build();
+ }
+
+ public static void addTepToElanInstance(DataBroker broker, String rd, String tepIp) {
+ if (rd == null || tepIp == null) {
+ LOG.error("addTepToElanInstance : Null parameters returning");
+ return;
+ }
+ String elanName = getElanNamefromRd(broker, rd);
+ if (elanName == null) {
+ LOG.error("Elan null while processing RT2 for RD {}", rd);
+ return;
+ }
+ LOG.debug("Adding tepIp {} to elan {}", tepIp, elanName);
+ InstanceIdentifier<ExternalTeps> externalTepsId = getExternalTepsIdentifier(elanName, tepIp);
+ ExternalTepsBuilder externalTepsBuilder = new ExternalTepsBuilder();
+ ExternalTepsKey externalTepsKey = externalTepsId.firstKeyOf(ExternalTeps.class);
+ externalTepsBuilder.setKey(externalTepsKey);
+ externalTepsBuilder.setTepIp(externalTepsKey.getTepIp());
+ BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, externalTepsId, externalTepsBuilder.build());
+ }
+
+ public static void deleteTepFromElanInstance(DataBroker broker, String rd, String tepIp) {
+ if (rd == null || tepIp == null) {
+ LOG.error("deleteTepFromElanInstance : Null parameters returning");
+ return;
+ }
+ String elanName = getElanNamefromRd(broker, rd);
+ if (elanName == null) {
+ LOG.error("Elan null while processing RT2 withdraw for RD {}", rd);
+ return;
+ }
+ LOG.debug("Deleting tepIp {} from elan {}", tepIp, elanName);
+ InstanceIdentifier<ExternalTeps> externalTepsId = getExternalTepsIdentifier(elanName, tepIp);
+ BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, externalTepsId);
+ }
+
+ public static InstanceIdentifier<ExternalTeps> getExternalTepsIdentifier(String elanInstanceName, String tepIp) {
+ IpAddress tepAdress = (tepIp == null) ? null : new IpAddress(tepIp.toCharArray());
+ return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class,
+ new ElanInstanceKey(elanInstanceName)).child(ExternalTeps.class,
+ new ExternalTepsKey(tepAdress)).build();
+ }
+
public static String getVpnNameFromRd(DataBroker dataBroker2, String rd) {
InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.create(VpnInstanceOpData.class)
.child(VpnInstanceOpDataEntry.class,
import org.apache.thrift.TException;
import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
-
+import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.TcpMd5SignaturePasswordType;
import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigureBgpCli.class);
private static BgpManager bgpManager;
+ private static BgpConfigurationManager bgpConfigurationManager;
+
private static final long AS_MIN = 0;
private static final long AS_MAX = 4294967295L;//2^32-1
}
@Option(name = "-op", aliases = {"--operation", "--op"}, description = "[start-bgp-server, stop-bgp-server, "
- + "add-neighbor, delete-neighbor, graceful-restart, enable-log ]",
+ + "add-neighbor, delete-neighbor, add-route, delete-route,graceful-restart, enable-log ]",
required = false, multiValued = false)
String op;
//exec configure-bgp add-neighbor --ip <neighbor-ip> --as-num <as-num> --address-family <af> --use-source-ip
// <sip> --ebgp-multihops <em> --next-hop <nh>
+ //exec configure-bgp --op add-route/delete-route --rd <rd> --prefix <prefix> --nexthop <nexthop>
+ // --mac <mac> --l2vni <l2vni> --l3vni <l3vni>
@Option(name = "--as-num", description = "as number of the bgp neighbor", required = false, multiValued = false)
String asNumber = null;
required = false, multiValued = false)
String routerId = null;
+ @Option(name = "--rd", description = "rd of the route",
+ required = false, multiValued = false)
+ String rd = null;
+
+ @Option(name = "--prefix", description = "prefix of the route",
+ required = false, multiValued = false)
+ String prefix = null;
+
+ @Option(name = "--nexthop", description = "nexthop of the route",
+ required = false, multiValued = false)
+ String nexthop = null;
+
+ @Option(name = "--mac", description = "mac of the route",
+ required = false, multiValued = false)
+ String mac = null;
+
+ @Option(name = "--l2vni", description = "l2vni of the route",
+ required = false, multiValued = false)
+ int l2vni = 0;
+
+ @Option(name = "--l3vni", description = "l3vni",
+ required = false, multiValued = false)
+ int l3vni = 0;
+
@Option(name = "--stalepath-time", description = "the time delay after bgp restart stalepaths are cleaned",
required = false, multiValued = false)
String stalePathTime = null;
usage();
session.getConsole().println(
"exec configure-bgp -op [start-bgp-server | stop-bgp-server | add-neighbor | delete-neighbor|"
- + " graceful-restart| enable-log ]");
+ + " add-route | delete-route | graceful-restart| enable-log ]");
}
switch (op) {
case "start-bgp-server":
case "delete-neighbor":
deleteNeighbor();
break;
+ case "add-route":
+ addRoute();
+ break;
+ case "delete-route":
+ deleteRoute();
+ break;
case "graceful-restart":
configureGR();
break;
}
}
+ protected void addRoute() throws Exception {
+ bgpConfigurationManager.onUpdatePushRoute(protocol_type.PROTOCOL_EVPN, rd, prefix,
+ 0, nexthop, 0, null, mac, l3vni, l2vni, null, null);
+ }
+
+ protected void deleteRoute() throws Exception {
+ bgpConfigurationManager.onUpdateWithdrawRoute(protocol_type.PROTOCOL_EVPN, rd, prefix,
+ 0, nexthop, mac);
+ }
+
private boolean validateIp(String inputIp) {
boolean validIp = false;
try {
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
-
+import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryKey;
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;
BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
}
+ public void addMacEntryToDS(String rd, String macAddress, String prefix,
+ List<String> nextHopList, VrfEntry.EncapType encapType,
+ long l2vni, String gatewayMacAddress, RouteOrigin origin) {
+ if (StringUtils.isEmpty(rd)) {
+ LOG.error("Mac {} not associated with vpn", macAddress);
+ return;
+ }
+
+ Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
+ for (String nextHop : nextHopList) {
+ if (StringUtils.isEmpty(nextHop)) {
+ LOG.error("nextHop list contains null element for macVrf");
+ return;
+ }
+ }
+
+ MacVrfEntryBuilder macEntryBuilder = new MacVrfEntryBuilder().setOrigin(origin.getValue());
+ buildVpnEncapSpecificInfo(macEntryBuilder, encapType, l2vni, macAddress,
+ gatewayMacAddress, nextHopList);
+ macEntryBuilder.setMac(macAddress);
+ macEntryBuilder.setDestPrefix(prefix);
+ InstanceIdentifier<MacVrfEntry> macEntryId =
+ InstanceIdentifier.builder(FibEntries.class)
+ .child(VrfTables.class, new VrfTablesKey(rd))
+ .child(MacVrfEntry.class, new MacVrfEntryKey(macAddress)).build();
+ BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, macEntryId, macEntryBuilder.build());
+ }
+
private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder,
VrfEntry.EncapType encapType, long label, long l3vni, String macAddress,
String gatewayMac, List<String> nextHopList) {
builder.setRoutePaths(routePaths);
}
+ private static void buildVpnEncapSpecificInfo(MacVrfEntryBuilder builder,
+ VrfEntry.EncapType encapType, long l2vni, String macAddress,
+ String gatewayMac, List<String> nextHopList) {
+ builder.setEncapType(encapType);
+ builder.setGatewayMacAddress(gatewayMac);
+ builder.setL2vni(l2vni);
+ List<RoutePaths> routePaths = nextHopList.stream()
+ .filter(nextHop -> StringUtils.isEmpty(nextHop))
+ .map(nextHop -> {
+ return FibHelper.buildRoutePath(nextHop, null);
+ }).collect(Collectors.toList());
+ builder.setRoutePaths(routePaths);
+ }
+
public synchronized void removeFibEntryFromDS(String rd, String prefix) {
if (rd == null || rd.isEmpty()) {
}
+ public void removeMacEntryFromDS(String rd, String macAddress) {
+
+ if (StringUtils.isEmpty(rd)) {
+ LOG.error("Mac {} not associated with vpn", macAddress);
+ return;
+ }
+ LOG.debug("Removing Mac fib entry with Mac {} from vrf table for rd {}", macAddress, rd);
+
+ InstanceIdentifierBuilder<MacVrfEntry> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
+ MacVrfEntry.class, new MacVrfEntryKey(macAddress));
+ InstanceIdentifier<MacVrfEntry> macEntryId = idBuilder.build();
+ BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, macEntryId);
+
+ }
+
public synchronized void removeOrUpdateFibEntryFromDS(String rd, String prefix, String nextHop) {
if (rd == null || rd.isEmpty()) {