diff --git a/alto-basic/auto-maps/api/pom.xml b/alto-basic/auto-maps/api/pom.xml index 661975d7..28caf49d 100644 --- a/alto-basic/auto-maps/api/pom.xml +++ b/alto-basic/auto-maps/api/pom.xml @@ -21,6 +21,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html 0.6.4 ODL :: alto :: ${project.artifactId} bundle + + 0.9.4 + org.opendaylight.alto.core @@ -35,5 +38,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html org.opendaylight.mdsal.model ietf-topology + + org.opendaylight.bgpcep + bgp-rib-api + ${bgpcep.version} + diff --git a/alto-basic/auto-maps/api/src/main/yang/alto-auto-maps.yang b/alto-basic/auto-maps/api/src/main/yang/alto-auto-maps.yang index 1179d1d9..a6954be6 100644 --- a/alto-basic/auto-maps/api/src/main/yang/alto-auto-maps.yang +++ b/alto-basic/auto-maps/api/src/main/yang/alto-auto-maps.yang @@ -11,6 +11,10 @@ module alto-auto-maps { prefix "topology"; } + import "bgp-rib" { + prefix "rib"; + } + import "alto-basic-types" { prefix "alto-types"; } @@ -71,13 +75,34 @@ module alto-auto-maps { } case bgp-simple-as-cluster { container bgp-simple-as-params { - // FIXME: identityref is better leaf bgp-rib { - type string; + type rib:rib-id; } } } } } + + list resource-cost-map { + key "resource-id"; + + leaf "resource-id" { + mandatory true; + type alto-types:resource-id; + } + + leaf "dependent-network-map" { + mandatory true; + type alto-types:resource-id; + } + + choice cost-algorithm { + case bgp-routes { + leaf-list alternative-bgp-ribs { + type rib:rib-id; + } + } + } + } } } diff --git a/alto-basic/auto-maps/impl/pom.xml b/alto-basic/auto-maps/impl/pom.xml index 33cc2449..fa4496d7 100644 --- a/alto-basic/auto-maps/impl/pom.xml +++ b/alto-basic/auto-maps/impl/pom.xml @@ -72,13 +72,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html org.opendaylight.bgpcep - bgp-rib-api + bgp-inet ${bgpcep.version} org.opendaylight.bgpcep - bgp-inet + bgp-linkstate ${bgpcep.version} diff --git a/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsBgpIpv4Updater.java b/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsBgpIpv4Updater.java index 3d7d279e..0524326f 100644 --- a/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsBgpIpv4Updater.java +++ b/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsBgpIpv4Updater.java @@ -10,6 +10,9 @@ import com.google.common.base.Optional; import org.opendaylight.alto.basic.manual.maps.ManualMapsUtils; import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.binding.api.ReadTransaction; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; @@ -35,117 +38,141 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.TablesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily; +import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; import java.util.Arrays; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutionException; -public class AltoAutoMapsBgpIpv4Updater implements AutoCloseable { +public class AltoAutoMapsBgpIpv4Updater implements DataTreeChangeListener, AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(AltoAutoMapsBgpIpv4Updater.class); private final DataBroker dataBroker; - // private ListenerRegistration registration; + private ListenerRegistration registration; private String contextId; private ResourceNetworkMap networkMapConfig; + private InstanceIdentifier tableIID; public AltoAutoMapsBgpIpv4Updater(String contextId, ResourceNetworkMap networkMapConfig, final DataBroker dataBroker) { this.dataBroker = dataBroker; this.contextId = contextId; this.networkMapConfig = networkMapConfig; + this.tableIID = getConfiguredIpv4Table(networkMapConfig); registerBGPListener(); } private void registerBGPListener() { - final ReadWriteTransaction wrx = dataBroker.newReadWriteTransaction(); - try { - List networkMap = computeNetworkMapByBgpIpv4(networkMapConfig); - LOG.info("Putting auto generated network-map to manual map config..."); - ManualMapsUtils.createResourceNetworkMap(contextId, networkMapConfig.getResourceId().getValue(), - networkMap, wrx); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); + if (tableIID != null) { + registration = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>( + LogicalDatastoreType.OPERATIONAL, tableIID), this); + LOG.info("Listening on BGP Ipv4 Routing Table:", tableIID); } + LOG.info("No routing table to listen"); + } + + private void updateNetworkMap() { + final ReadWriteTransaction wrx = dataBroker.newReadWriteTransaction(); + List networkMap = computeNetworkMapByBgpIpv4(networkMapConfig); + LOG.info("Putting auto generated network-map to manual map config..."); + ManualMapsUtils.createResourceNetworkMap(contextId, networkMapConfig.getResourceId().getValue(), + networkMap, wrx); wrx.submit(); } - private List computeNetworkMapByBgpIpv4(ResourceNetworkMap networkMapConfig) throws InterruptedException, ExecutionException { - final ReadTransaction rx = dataBroker.newReadOnlyTransaction(); - List networkMap = new LinkedList<>(); + private InstanceIdentifier getConfiguredIpv4Table(ResourceNetworkMap networkMapConfig) { if (networkMapConfig.getAlgorithm() instanceof BgpSimpleAsCluster) { BgpSimpleAsCluster algorithm = (BgpSimpleAsCluster) networkMapConfig.getAlgorithm(); - String ribId = algorithm.getBgpSimpleAsParams().getBgpRib(); - InstanceIdentifier ribIID = InstanceIdentifier.builder(BgpRib.class) - .child(Rib.class, new RibKey(new RibId(ribId))) + RibId ribId = algorithm.getBgpSimpleAsParams().getBgpRib(); + return InstanceIdentifier.builder(BgpRib.class) + .child(Rib.class, new RibKey(ribId)) .child(LocRib.class) .child(Tables.class, new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class)) .build(); - try { - Optional optional = rx.read(LogicalDatastoreType.OPERATIONAL, ribIID).get(); - if (optional.isPresent()) { - Tables table = optional.get(); - if (table.getRoutes() instanceof Ipv4RoutesCase) { - Ipv4RoutesCase routesCase = (Ipv4RoutesCase) table.getRoutes(); - java.util.Map> pids = new LinkedHashMap<>(); - for (Ipv4Route route : routesCase.getIpv4Routes().getIpv4Route()) { - List segments = route.getAttributes().getAsPath().getSegments(); - String pidName = "PID0"; - if (segments != null && !segments.isEmpty()) { - List asSequence = segments.get(segments.size() - 1).getAsSequence(); - if (asSequence != null && !asSequence.isEmpty()) { - pidName = "PID" + asSequence.get(asSequence.size() - 1).getValue().toString(); - } else { - List asSet = segments.get(segments.size() - 1).getAsSet(); - if (asSet != null && !asSet.isEmpty()) { - pidName = "PID" + String.join("-", - (String[]) Arrays.stream((AsNumber[]) asSet.toArray()) - .map(s -> s.getValue().toString()) - .toArray()); - } - } - } - if (!pids.containsKey(pidName)) { - pids.put(pidName, new LinkedList<>()); - } - pids.get(pidName).add(new IpPrefix(route.getPrefix())); - } - for (java.util.Map.Entry> entry : pids.entrySet()) { - String pidName = entry.getKey(); - List prefixList = entry.getValue(); - networkMap.add(new MapBuilder() - .setPid(new PidName(pidName)) - .setEndpointAddressGroup(Arrays.asList(new EndpointAddressGroup[]{ - new EndpointAddressGroupBuilder() - .setAddressType(new EndpointAddressType(EndpointAddressType.Enumeration.Ipv4)) - .setEndpointPrefix(prefixList) - .build() - })) - .build()); - } - } else { - throw new ExecutionException("Unsupported route type", null); + } else { + LOG.error("Unsupported algorithm for bgp topology"); + } + return null; + } + + @Override + public void onDataTreeChanged(@Nonnull Collection> changes) { + updateNetworkMap(); + } + + private List computeNetworkMapByBgpIpv4(ResourceNetworkMap networkMapConfig) { + final ReadTransaction rx = dataBroker.newReadOnlyTransaction(); + List networkMap = new LinkedList<>(); + try { + Optional optional = rx.read(LogicalDatastoreType.OPERATIONAL, tableIID).get(); + if (optional.isPresent()) { + Tables table = optional.get(); + if (table.getRoutes() instanceof Ipv4RoutesCase) { + java.util.Map> pids = getPIDClusters((Ipv4RoutesCase) table.getRoutes()); + for (java.util.Map.Entry> entry : pids.entrySet()) { + String pidName = entry.getKey(); + List prefixList = entry.getValue(); + networkMap.add(new MapBuilder() + .setPid(new PidName(pidName)) + .setEndpointAddressGroup(Arrays.asList(new EndpointAddressGroup[]{ + new EndpointAddressGroupBuilder() + .setAddressType(new EndpointAddressType(EndpointAddressType.Enumeration.Ipv4)) + .setEndpointPrefix(prefixList) + .build() + })) + .build()); } } else { - throw new InterruptedException("BGP Local RIB not found"); + LOG.error("Unsupported route type"); } - } catch (InterruptedException | ExecutionException e) { - throw e; + } else { + LOG.error("BGP Local RIB not found"); } - } else { - throw new InterruptedException("Unsupported algorithm for bgp topology"); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); } return networkMap; } + private java.util.Map> getPIDClusters(Ipv4RoutesCase routesCase) { + java.util.Map> pids = new LinkedHashMap<>(); + for (Ipv4Route route : routesCase.getIpv4Routes().getIpv4Route()) { + List segments = route.getAttributes().getAsPath().getSegments(); + String pidName = "PID0"; + if (segments != null && !segments.isEmpty()) { + List asSequence = segments.get(segments.size() - 1).getAsSequence(); + if (asSequence != null && !asSequence.isEmpty()) { + pidName = "PID" + asSequence.get(asSequence.size() - 1).getValue().toString(); + } else { + List asSet = segments.get(segments.size() - 1).getAsSet(); + if (asSet != null && !asSet.isEmpty()) { + pidName = "PID" + String.join("-", + (String[]) Arrays.stream((AsNumber[]) asSet.toArray()) + .map(s -> s.getValue().toString()) + .toArray()); + } + } + } + if (!pids.containsKey(pidName)) { + pids.put(pidName, new LinkedList<>()); + } + pids.get(pidName).add(new IpPrefix(route.getPrefix())); + } + return pids; + } + @Override public void close() throws Exception { + if (registration != null) { + registration.close(); + } LOG.info("BGP IPv4 updater closed"); } } diff --git a/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsBgpLsUpdater.java b/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsBgpLsUpdater.java new file mode 100644 index 00000000..e019d873 --- /dev/null +++ b/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsBgpLsUpdater.java @@ -0,0 +1,252 @@ +/* + * Copyright © 2015 Yale University 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.alto.basic.impl; + +import com.google.common.base.Optional; +import org.opendaylight.alto.basic.manual.maps.ManualMapsUtils; +import org.opendaylight.alto.basic.manual.maps.MatchedIPPrefix; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.controller.md.sal.binding.api.ReadTransaction; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.alto.auto.maps.rev150105.config.context.ResourceNetworkMap; +import org.opendaylight.yang.gen.v1.urn.alto.auto.maps.rev150105.config.context.resource.network.map.algorithm.BgpSimpleAsCluster; +import org.opendaylight.yang.gen.v1.urn.alto.manual.maps.networkmap.rev151021.EndpointAddressType; +import org.opendaylight.yang.gen.v1.urn.alto.manual.maps.networkmap.rev151021.endpoint.address.group.EndpointAddressGroup; +import org.opendaylight.yang.gen.v1.urn.alto.manual.maps.networkmap.rev151021.endpoint.address.group.EndpointAddressGroupBuilder; +import org.opendaylight.yang.gen.v1.urn.alto.manual.maps.networkmap.rev151021.network.map.Map; +import org.opendaylight.yang.gen.v1.urn.alto.manual.maps.networkmap.rev151021.network.map.MapBuilder; +import org.opendaylight.yang.gen.v1.urn.alto.types.rev150921.PidName; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.AreaIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.DomainIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.LinkstateAddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.LinkstateSubsequentAddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.ProtocolId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.linkstate.object.type.LinkCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.linkstate.object.type.PrefixCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.linkstate.object.type.link._case.LocalNodeDescriptors; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.linkstate.object.type.link._case.RemoteNodeDescriptors; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.linkstate.object.type.prefix._case.AdvertisingNodeDescriptors; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.linkstate.routes.linkstate.routes.LinkstateRoute; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.node.identifier.CRouterIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.node.identifier.c.router.identifier.OspfNodeCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev171207.node.identifier.c.router.identifier.ospf.node._case.OspfNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.BgpRib; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.RibId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.bgp.rib.Rib; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.bgp.rib.RibKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.bgp.rib.rib.LocRib; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.Tables; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.TablesKey; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ExecutionException; + +public class AltoAutoMapsBgpLsUpdater implements DataTreeChangeListener, AutoCloseable { + + private static final Logger LOG = LoggerFactory.getLogger(AltoAutoMapsBgpLsUpdater.class); + + private final DataBroker dataBroker; + private ListenerRegistration registration; + private String contextId; + private ResourceNetworkMap networkMapConfig; + private InstanceIdentifier tableIID; + + public AltoAutoMapsBgpLsUpdater(String contextId, ResourceNetworkMap networkMapConfig, final DataBroker dataBroker) { + this.dataBroker = dataBroker; + this.contextId = contextId; + this.networkMapConfig = networkMapConfig; + this.tableIID = getConfiguredLinkStateTable(networkMapConfig); + } + + private InstanceIdentifier getConfiguredLinkStateTable(ResourceNetworkMap networkMapConfig) { + if (networkMapConfig.getAlgorithm() instanceof BgpSimpleAsCluster) { + BgpSimpleAsCluster algorithm = (BgpSimpleAsCluster) networkMapConfig.getAlgorithm(); + RibId ribId = algorithm.getBgpSimpleAsParams().getBgpRib(); + return InstanceIdentifier.builder(BgpRib.class) + .child(Rib.class, new RibKey(ribId)) + .child(LocRib.class) + .child(Tables.class, + new TablesKey(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class)) + .build(); + } else { + LOG.error("Unsupported algorithm for bgp topology"); + } + return null; + } + + @Override + public void onDataTreeChanged(@Nonnull Collection> changes) { + updateNetworkMap(); + } + + private void updateNetworkMap() { + final ReadWriteTransaction wrx = dataBroker.newReadWriteTransaction(); + List networkMap = computeNetworkMapByBgpLs(networkMapConfig); + LOG.info("Putting auto generated network-map to manual map config..."); + ManualMapsUtils.createResourceNetworkMap(contextId, networkMapConfig.getResourceId().getValue(), + networkMap, wrx); + wrx.submit(); + } + + private List computeNetworkMapByBgpLs(ResourceNetworkMap networkMapConfig) { + final ReadTransaction rx = dataBroker.newReadOnlyTransaction(); + List networkMap = new LinkedList<>(); + try { + Optional optional = rx.read(LogicalDatastoreType.OPERATIONAL, tableIID).get(); + if (optional.isPresent()) { + Tables table = optional.get(); + if (table.getRoutes() instanceof LinkstateRoutesCase) { + java.util.Map> pids = getPIDClusters((LinkstateRoutesCase) table.getRoutes()); + for (java.util.Map.Entry> entry : pids.entrySet()) { + String pidName = entry.getKey(); + List prefixList = entry.getValue(); + networkMap.add(new MapBuilder() + .setPid(new PidName(pidName)) + .setEndpointAddressGroup(Arrays.asList(new EndpointAddressGroup[]{ + new EndpointAddressGroupBuilder() + .setAddressType(new EndpointAddressType(EndpointAddressType.Enumeration.Ipv4)) + .setEndpointPrefix(prefixList) + .build() + })) + .build()); + } + } else { + LOG.error("Unsupported route type"); + } + } else { + LOG.error("BGP Local RIB not found"); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return networkMap; + } + + private java.util.Map> getPIDClusters(LinkstateRoutesCase routesCase) { + java.util.Map> pids = new LinkedHashMap<>(); + for (LinkstateRoute route : routesCase.getLinkstateRoutes().getLinkstateRoute()) { + if (route.getProtocolId() == ProtocolId.Ospf) { + if (route.getObjectType() instanceof PrefixCase) { + PrefixCase prefixCase = (PrefixCase) route.getObjectType(); + IpPrefix prefix = prefixCase.getPrefixDescriptors().getIpReachabilityInformation(); + AdvertisingNodeDescriptors nodeDesc = prefixCase.getAdvertisingNodeDescriptors(); + String pidName = generatePidFromNodeDesc(nodeDesc.getAsNumber(), nodeDesc.getDomainId(), + nodeDesc.getAreaId(), nodeDesc.getCRouterIdentifier()); + if (pidName != null && prefix != null) { + if (!pids.containsKey(pidName)) { + pids.put(pidName, new LinkedList<>()); + } + boolean include = true; + for (IpPrefix p : pids.get(pidName)) { + if (matchPrefix(p, prefix)) { + include = false; + break; + } + } + if (include) { + pids.get(pidName).add(prefix); + } + } + } else if (route.getObjectType() instanceof LinkCase) { + LinkCase linkCase = (LinkCase) route.getObjectType(); + Ipv4Address src = linkCase.getLinkDescriptors().getIpv4InterfaceAddress(); + Ipv4Address dst = linkCase.getLinkDescriptors().getIpv4NeighborAddress(); + LocalNodeDescriptors srcNodeDesc = linkCase.getLocalNodeDescriptors(); + RemoteNodeDescriptors dstNodeDesc = linkCase.getRemoteNodeDescriptors(); + String srcPidName = generatePidFromNodeDesc(srcNodeDesc.getAsNumber(), srcNodeDesc.getDomainId(), + srcNodeDesc.getAreaId(), srcNodeDesc.getCRouterIdentifier()); + String dstPidName = generatePidFromNodeDesc(dstNodeDesc.getAsNumber(), dstNodeDesc.getDomainId(), + dstNodeDesc.getAreaId(), dstNodeDesc.getCRouterIdentifier()); + if (srcPidName != null && src != null) { + if (!pids.containsKey(srcPidName)) { + pids.put(srcPidName, new LinkedList<>()); + } + IpPrefix srcPrefix = new IpPrefix(new Ipv4Prefix(src.getValue() + "/32")); + List removes = new LinkedList<>(); + for (IpPrefix p : pids.get(srcPidName)) { + if (matchPrefix(srcPrefix, p)) { + removes.add(p); + } + } + pids.get(srcPidName).removeAll(removes); + pids.get(srcPidName).add(srcPrefix); + } + if (dstPidName != null && dst != null) { + if (!pids.containsKey(dstPidName)) { + pids.put(dstPidName, new LinkedList<>()); + } + IpPrefix dstPrefix = new IpPrefix((new Ipv4Prefix(dst.getValue() + "/32"))); + List removes = new LinkedList<>(); + for (IpPrefix p : pids.get(dstPidName)) { + if (matchPrefix(dstPrefix, p)) { + removes.add(p); + } + } + pids.get(dstPidName).removeAll(removes); + pids.get(dstPidName).add(dstPrefix); + } + } + } else { + LOG.debug("Protocol not supported yet"); + } + } + return pids; + } + + /* Return if p in prefix */ + private boolean matchPrefix(IpPrefix p, IpPrefix prefix) { + String _pStr = p.getIpv4Prefix() != null ? + p.getIpv4Prefix().getValue() : p.getIpv6Prefix().getValue(); + String _prefrixStr = prefix.getIpv4Prefix() != null ? + prefix.getIpv4Prefix().getValue() : prefix.getIpv6Prefix().getValue(); + return new MatchedIPPrefix(_prefrixStr).match(new MatchedIPPrefix(_pStr)); + } + + private String generatePidFromNodeDesc(AsNumber asNumber, DomainIdentifier domainId, AreaIdentifier areaId, + CRouterIdentifier cRouterId) { + String pidName = "PID"; + pidName += (asNumber == null) ? "0" : asNumber.getValue().toString(); + pidName += "." + ((domainId == null) ? "0" : domainId.getValue().toString()); + pidName += "." + ((areaId == null) ? "0" : areaId.getValue().toString()); + if (cRouterId instanceof OspfNodeCase) { + OspfNode ospfNode = ((OspfNodeCase) cRouterId).getOspfNode(); + pidName += "." + Integer.toHexString(ospfNode.getOspfRouterId().intValue()); + } else { + LOG.debug("Node not support yet"); + return null; + } + return pidName; + } + + @Override + public void close() throws Exception { + if (registration != null) { + registration.close(); + } + LOG.info("BGP IPv4 updater closed"); + } +} diff --git a/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsConfigListener.java b/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsConfigListener.java index 2cf39a56..af361b39 100644 --- a/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsConfigListener.java +++ b/alto-basic/auto-maps/impl/src/main/java/org/opendaylight/alto/basic/impl/AltoAutoMapsConfigListener.java @@ -129,8 +129,9 @@ private void generateNetworkMapUpdater(String contextId, String resourceId, Reso dataBroker)); break; case BgpLs: - // TODO: BGP-LS updater - LOG.warn("BGP-LS updater not implemented yet"); + LOG.info("creating updater for BGP-LS topology"); + contextUpdaters.put(resourceId, new AltoAutoMapsBgpLsUpdater(contextId, networkMapConfig, + dataBroker)); break; default: LOG.warn("Unsupported topology type"); diff --git a/alto-basic/manual-maps/api/src/main/java/org/opendaylight/alto/basic/manual/maps/ManualMapsUtils.java b/alto-basic/manual-maps/api/src/main/java/org/opendaylight/alto/basic/manual/maps/ManualMapsUtils.java index 3671bea7..488fdbbc 100644 --- a/alto-basic/manual-maps/api/src/main/java/org/opendaylight/alto/basic/manual/maps/ManualMapsUtils.java +++ b/alto-basic/manual-maps/api/src/main/java/org/opendaylight/alto/basic/manual/maps/ManualMapsUtils.java @@ -100,10 +100,8 @@ public static InstanceIdentifier getResourceCostMapIID(String c } public static InstanceIdentifier getResourceCostMapIID(Uuid cid, ResourceId rid) { - ConfigContextKey ckey = new ConfigContextKey(cid); - ResourceCostMapKey rkey = new ResourceCostMapKey(rid); return getResourceIID(new ConfigContextKey(cid), new ResourceCostMapKey(rid), - ResourceCostMap.class); + ResourceCostMap.class); } public static & ChildOf, K extends Identifier> @@ -150,7 +148,7 @@ public static InstanceIdentifier createResourceNetworkMap(Uu WriteTransaction wx) { InstanceIdentifier iid = getResourceNetworkMapIID(cid, rid); ResourceNetworkMapBuilder builder = new ResourceNetworkMapBuilder() - .setTag(new Tag(UUID.nameUUIDFromBytes(rid.getValue().getBytes()) + .setTag(new Tag(UUID.randomUUID() .toString() .replaceAll("-", ""))) .setResourceId(rid) @@ -165,7 +163,7 @@ public static InstanceIdentifier createResourceCostMap(String r WriteTransaction wx) { InstanceIdentifier iid = getResourceCostMapIID(rid); ResourceCostMapBuilder builder = new ResourceCostMapBuilder() - .setTag(new Tag(UUID.nameUUIDFromBytes(rid.getBytes()) + .setTag(new Tag(UUID.randomUUID() .toString() .replaceAll("-", ""))) .setResourceId(new ResourceId(rid)) @@ -189,7 +187,7 @@ public static void deleteResourceNetworkMap(String rid, final WriteTransaction w } public static void deleteResourceNetworkMap(String cid, String rid, final WriteTransaction wx) { - deleteResourceNetworkMap(new Uuid(cid), new ResourceId(cid), wx); + deleteResourceNetworkMap(new Uuid(cid), new ResourceId(rid), wx); } public static void deleteResourceNetworkMap(Uuid cid, ResourceId rid, @@ -202,7 +200,7 @@ public static void deleteResourceCostMap(String rid, final WriteTransaction wx) } public static void deleteResourceCostMap(String cid, String rid, final WriteTransaction wx) { - deleteResourceCostMap(new Uuid(cid), new ResourceId(cid), wx); + deleteResourceCostMap(new Uuid(cid), new ResourceId(rid), wx); } public static void deleteResourceCostMap(Uuid cid, ResourceId rid, final WriteTransaction wx) { diff --git a/alto-basic/manual-maps/api/src/main/java/org/opendaylight/alto/basic/manual/maps/MatchedIPPrefix.java b/alto-basic/manual-maps/api/src/main/java/org/opendaylight/alto/basic/manual/maps/MatchedIPPrefix.java new file mode 100644 index 00000000..30d51d4b --- /dev/null +++ b/alto-basic/manual-maps/api/src/main/java/org/opendaylight/alto/basic/manual/maps/MatchedIPPrefix.java @@ -0,0 +1,66 @@ +/* + * Copyright © 2015 Yale University 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.alto.basic.manual.maps; + +import javax.annotation.Nonnull; +import java.net.InetAddress; +import java.net.UnknownHostException; + +public class MatchedIPPrefix { + private final int prefixLen; + private final InetAddress baseAddress; + + public MatchedIPPrefix(String ipAddress) { + int _prefixLen = -1; + if (ipAddress.indexOf('/') > 0) { + String[] baseAndLen = ipAddress.split("/"); + ipAddress = baseAndLen[0]; + _prefixLen = Integer.parseInt(baseAndLen[1]); + } + try { + baseAddress = InetAddress.getByName(ipAddress); + } catch (UnknownHostException e) { + throw new IllegalArgumentException("Failed to parse address " + ipAddress, e); + } + if (_prefixLen < 0) { + _prefixLen = baseAddress.getAddress().length * 8; + } + prefixLen = _prefixLen; + assert (baseAddress.getAddress().length * 8 >= prefixLen): + String.format("Prefix length %d is too long for the base IP address %s", prefixLen, baseAddress); + } + + /** + * Return if the current IP prefix can cover the taken specific IP prefix. + * + * @param specificPrefix a specific IP prefix. + * @return if the taken specific IP prefix is covered. + */ + public boolean match(@Nonnull MatchedIPPrefix specificPrefix) { + if (!baseAddress.getClass().equals(specificPrefix.baseAddress.getClass())) { + return false; + } + if (specificPrefix.prefixLen > prefixLen) { + return false; + } + byte[] baseAddr = baseAddress.getAddress(); + byte[] specAddr = specificPrefix.baseAddress.getAddress(); + + int nMaskedFullBytes = prefixLen / 8; + byte lastByteMask = (byte) (0xFF00 >> (prefixLen & 0x07)); + for (int i = 0; i < nMaskedFullBytes; i++) { + if (baseAddr[i] != specAddr[i]) { + return false; + } + } + if (lastByteMask != 0) { + return (baseAddr[nMaskedFullBytes] & lastByteMask) == (specAddr[nMaskedFullBytes] & lastByteMask); + } + return true; + } +} diff --git a/utils/gen_patch_kar.sh b/utils/gen_patch_kar.sh index 1ec27706..3e355594 100755 --- a/utils/gen_patch_kar.sh +++ b/utils/gen_patch_kar.sh @@ -10,12 +10,13 @@ cd $(dirname $0)/.. PROJECT_ROOT=$(pwd) KAR_ROOT=$PROJECT_ROOT/alto-karaf/target/assembly -ALTO_KAR_ROOT=$KAR_ROOT/system/org/opendaylight/alto +ALTO_KAR_ROOT=$KAR_ROOT/system/org/opendaylight/alto/ generate_patch() { TMP_DIR=$(mktemp -d) TMP_PATCH_ROOT=$TMP_DIR/odl-alto-patch - cp -r $ALTO_KAR_ROOT $TMP_PATCH_ROOT/ + mkdir -p $TMP_PATCH_ROOT/alto + cp -r $ALTO_KAR_ROOT $TMP_PATCH_ROOT/alto/ cp $PROJECT_ROOT/utils/install_patch.sh $TMP_PATCH_ROOT/ pushd $TMP_DIR zip -r odl-alto-patch odl-alto-patch