X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=bgp%2Frib-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fconfig%2Fyang%2Fbgp%2Frib%2Fimpl%2FBGPPeerModule.java;h=ada1deba45b4ee61c9b3de6778856132ba725d8d;hb=c1d5824ad47f83684192c9dd9f9b94f88a8cf4b5;hp=47490ee124de903aeab77e7d9caa51393592f17f;hpb=a9af7cc08b64f3f6b07d493a1151ba30a3cfe4f8;p=bgpcep.git diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java old mode 100644 new mode 100755 index 47490ee124..ada1deba45 --- a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java @@ -16,30 +16,48 @@ */ package org.opendaylight.controller.config.yang.bgp.rib.impl; -import com.google.common.base.Charsets; -import com.google.common.collect.Lists; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; import com.google.common.net.InetAddresses; +import io.netty.channel.epoll.Epoll; import io.netty.util.concurrent.Future; - import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; - -import org.opendaylight.bgpcep.tcpmd5.KeyMapping; +import java.util.Map; import org.opendaylight.controller.config.api.JmxAttributeValidationException; +import org.opendaylight.protocol.bgp.openconfig.spi.BGPConfigModuleTracker; +import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigProvider; +import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenconfigMapper; +import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfigurationIdentifier; +import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPPeerInstanceConfiguration; +import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl; +import org.opendaylight.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil; import org.opendaylight.protocol.bgp.rib.impl.BGPPeer; import org.opendaylight.protocol.bgp.rib.impl.StrictBGPPeerRegistry; import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry; import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences; import org.opendaylight.protocol.bgp.rib.impl.spi.RIB; +import org.opendaylight.protocol.concepts.KeyMapping; +import org.opendaylight.protocol.util.Ipv6Util; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParametersBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.c.parameters.As4BytesCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.c.parameters.as4.bytes._case.As4BytesCapabilityBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParametersBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilities; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.MultiprotocolCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.multiprotocol._case.MultiprotocolCapabilityBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.AddPathCapabilityBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.GracefulRestartCapabilityBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.MultiprotocolCapabilityBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.add.path.capability.AddressFamilies; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.rfc2385.cfg.rev160324.Rfc2385Key; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,52 +68,46 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang private static final Logger LOG = LoggerFactory.getLogger(BGPPeerModule.class); public BGPPeerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, - final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); } public BGPPeerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, - final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final BGPPeerModule oldModule, - final java.lang.AutoCloseable oldInstance) { + final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final BGPPeerModule oldModule, + final java.lang.AutoCloseable oldInstance) { super(identifier, dependencyResolver, oldModule, oldInstance); } @Override protected void customValidation() { - JmxAttributeValidationException.checkNotNull(getHost(), "value is not set.", hostJmxAttribute); - JmxAttributeValidationException.checkNotNull(getPort(), "value is not set.", portJmxAttribute); + final IpAddress host = getHost(); + JmxAttributeValidationException.checkNotNull(host, "value is not set.", hostJmxAttribute); + JmxAttributeValidationException.checkCondition(host.getIpv4Address() != null || host.getIpv6Address() != null, + "Unexpected host", hostJmxAttribute); - if (getPassword() != null) { - /* - * This is a nasty hack, but we don't have another clean solution. We cannot allow - * password being set if the injected dispatcher does not have the optional - * md5-server-channel-factory set. - * - * FIXME: this is a use case for Module interfaces, e.g. RibImplModule - * should something like isMd5ServerSupported() - */ - - RIBImplModuleMXBean ribProxy = dependencyResolver.newMXBeanProxy(getRib(), RIBImplModuleMXBean.class); - BGPDispatcherImplModuleMXBean bgpDispatcherProxy = dependencyResolver.newMXBeanProxy( - ribProxy.getBgpDispatcher(), BGPDispatcherImplModuleMXBean.class); - boolean isMd5Supported = bgpDispatcherProxy.getMd5ChannelFactory() != null; + JmxAttributeValidationException.checkNotNull(getPort(), "value is not set.", portJmxAttribute); - JmxAttributeValidationException.checkCondition(isMd5Supported, - "Underlying dispatcher does not support MD5 clients", passwordJmxAttribute); + if (getPeerRole() != null) { + final boolean isNotPeerRoleInternal= getPeerRole() != PeerRole.Internal; + JmxAttributeValidationException.checkCondition(isNotPeerRoleInternal, + "Internal Peer Role is reserved for Application Peer use.", peerRoleJmxAttribute); + } + if (getOptionalPassword(getPassword()).isPresent()) { + JmxAttributeValidationException.checkCondition(Epoll.isAvailable(), + "BGP Peer is configured with password but native transport is not available", passwordJmxAttribute); } + } private InetSocketAddress createAddress() { final IpAddress ip = getHost(); + Preconditions.checkArgument(ip.getIpv4Address() != null || ip.getIpv6Address() != null, "Failed to handle host %s", ip); if (ip.getIpv4Address() != null) { return new InetSocketAddress(InetAddresses.forString(ip.getIpv4Address().getValue()), getPort().getValue()); - } else if (ip.getIpv6Address() != null) { - return new InetSocketAddress(InetAddresses.forString(ip.getIpv6Address().getValue()), getPort().getValue()); - } else { - throw new IllegalStateException("Failed to handle host " + getHost()); } + return new InetSocketAddress(InetAddresses.forString(ip.getIpv6Address().getValue()), getPort().getValue()); } @Override @@ -104,24 +116,34 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang final List tlvs = getTlvs(r); final AsNumber remoteAs = getAsOrDefault(r); - final String password = getPasswordOrNull(); + final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), remoteAs, tlvs); + final BGPPeer bgpClientPeer; + final IpAddress host = getNormalizedHost(); + if (getPeerRole() != null) { + bgpClientPeer = new BGPPeer(peerName(host), r, getPeerRole(), getSimpleRoutingPolicy(), getRpcRegistryDependency()); + } else { + bgpClientPeer = new BGPPeer(peerName(host), r, PeerRole.Ibgp, getSimpleRoutingPolicy(), getRpcRegistryDependency()); + } - final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), tlvs); - final BGPPeer bgpClientPeer = new BGPPeer(peerName(getHostWithoutValue()), r); + bgpClientPeer.registerRootRuntimeBean(getRootRuntimeBeanRegistratorWrapper()); - getPeerRegistryBackwards().addPeer(getHostWithoutValue(), bgpClientPeer, prefs); + getPeerRegistryBackwards().addPeer(host, bgpClientPeer, prefs); + + final BGPPeerModuleTracker moduleTracker = new BGPPeerModuleTracker(r.getOpenConfigProvider()); + moduleTracker.onInstanceCreate(); final CloseableNoEx peerCloseable = new CloseableNoEx() { @Override public void close() { bgpClientPeer.close(); - getPeerRegistryBackwards().removePeer(getHostWithoutValue()); + getPeerRegistryBackwards().removePeer(host); + moduleTracker.onInstanceClose(); } }; // Initiate connection if(getInitiateConnection()) { - final Future cf = initiateConnection(createAddress(), password, remoteAs, getPeerRegistryBackwards()); + final Future cf = initiateConnection(createAddress(), getOptionalPassword(getPassword()), getPeerRegistryBackwards()); return new CloseableNoEx() { @Override public void close() { @@ -134,22 +156,12 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang } } - private static interface CloseableNoEx extends AutoCloseable { + private interface CloseableNoEx extends AutoCloseable { @Override void close(); } - private String getPasswordOrNull() { - final String password; - if (getPassword() != null) { - password = getPassword().getValue(); - } else { - password = null; - } - return password; - } - - private AsNumber getAsOrDefault(RIB r) { + private AsNumber getAsOrDefault(final RIB r) { // Remote AS number defaults to our local AS final AsNumber remoteAs; if (getRemoteAs() != null) { @@ -160,47 +172,62 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang return remoteAs; } - private List getTlvs(RIB r) { - final List tlvs = Lists.newArrayList(); - tlvs.add(new BgpParametersBuilder().setCParameters( - new As4BytesCaseBuilder().setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(r.getLocalAs()).build()).build()).build()); + private List getTlvs(final RIB r) { + final List tlvs = new ArrayList<>(); + final List caps = new ArrayList<>(); + caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability( + new As4BytesCapabilityBuilder().setAsNumber(r.getLocalAs()).build()).build()).build()); + caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class, + new CParameters1Builder().setGracefulRestartCapability(new GracefulRestartCapabilityBuilder().build()).build()).build()).build()); + + if (getRouteRefresh()) { + caps.add(new OptionalCapabilitiesBuilder().setCParameters(MultiprotocolCapabilitiesUtil.RR_CAPABILITY).build()); + } + + if (!getAddPathDependency().isEmpty()) { + final List addPathFamilies = filterAddPathDependency(getAddPathDependency()); + caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class, + new CParameters1Builder().setAddPathCapability(new AddPathCapabilityBuilder().setAddressFamilies(addPathFamilies).build()).build()).build()).build()); + } for (final BgpTableType t : getAdvertizedTableDependency()) { if (!r.getLocalTables().contains(t)) { LOG.info("RIB instance does not list {} in its local tables. Incoming data will be dropped.", t); } - tlvs.add(new BgpParametersBuilder().setCParameters( - new MultiprotocolCaseBuilder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder(t).build()).build()).build()); + caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class, + new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder(t).build()).build()).build()).build()); } + tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(caps).build()); return tlvs; } - public IpAddress getHostWithoutValue() { - // FIXME we need to remove field "value" from IpAddress since equals does not work as expected when value being present - // Remove after this bug is fixed https://bugs.opendaylight.org/show_bug.cgi?id=1276 - final IpAddress host = super.getHost(); - if(host.getIpv4Address() != null) { - return new IpAddress(host.getIpv4Address()); - } else if(host.getIpv6Address() != null){ - return new IpAddress(host.getIpv6Address()); + private List filterAddPathDependency(final List addPathDependency) { + final Map filteredFamilies = new HashMap(); + for (final AddressFamilies family : addPathDependency) { + final BgpTableType key = new BgpTableTypeImpl(family.getAfi(), family.getSafi()); + if (!filteredFamilies.containsKey(key)) { + filteredFamilies.put(key, family); + } else { + LOG.info("Ignoring Add-path dependency {}", family); + } } - - throw new IllegalArgumentException("Unexpected host " + host); + return new ArrayList(filteredFamilies.values()); } - private io.netty.util.concurrent.Future initiateConnection(final InetSocketAddress address, final String password, final AsNumber remoteAs, final BGPPeerRegistry registry) { - final KeyMapping keys; - if (password != null) { - keys = new KeyMapping(); - keys.put(address.getAddress(), password.getBytes(Charsets.US_ASCII)); - } else { - keys = null; + public IpAddress getNormalizedHost() { + final IpAddress host = getHost(); + if(host.getIpv6Address() != null){ + return new IpAddress(Ipv6Util.getFullForm(host.getIpv6Address())); } + return host; + } + private io.netty.util.concurrent.Future initiateConnection(final InetSocketAddress address, final Optional password, final BGPPeerRegistry registry) { + KeyMapping keys = KeyMapping.getKeyMapping(address.getAddress(), password); final RIB rib = getRibDependency(); - return rib.getDispatcher().createReconnectingClient(address, remoteAs, registry, rib.getTcpStrategyFactory(), - rib.getSessionStrategyFactory(), keys); + final Optional optionalKey = Optional.fromNullable(keys); + return rib.getDispatcher().createReconnectingClient(address, registry, getRetrytimer(), optionalKey); } private BGPPeerRegistry getPeerRegistryBackwards() { @@ -218,4 +245,42 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang return null; } -} + private final class BGPPeerModuleTracker implements BGPConfigModuleTracker { + + private final BGPOpenconfigMapper neighborProvider; + private final BGPPeerInstanceConfiguration bgpPeerInstanceConfiguration; + + public BGPPeerModuleTracker(final Optional openconfigProvider) { + if (openconfigProvider.isPresent()) { + this.neighborProvider = openconfigProvider.get().getOpenConfigMapper(BGPPeerInstanceConfiguration.class); + } else { + this.neighborProvider = null; + } + final InstanceConfigurationIdentifier identifier = new InstanceConfigurationIdentifier(getIdentifier().getInstanceName()); + this.bgpPeerInstanceConfiguration = new BGPPeerInstanceConfiguration(identifier, Rev130715Util.getIpvAddress(getNormalizedHost()), + Rev130715Util.getPort(getPort().getValue()), getHoldtimer(), getPeerRole(), getInitiateConnection(), + getAdvertizedTableDependency(), Rev130715Util.getASNumber(getAsOrDefault(getRibDependency()).getValue()), + getOptionalPassword(getPassword()), getAddPathDependency()); + } + + @Override + public void onInstanceCreate() { + if (this.neighborProvider != null) { + this.neighborProvider.writeConfiguration(this.bgpPeerInstanceConfiguration); + } + } + + @Override + public void onInstanceClose() { + if (this.neighborProvider != null) { + this.neighborProvider.removeConfiguration(this.bgpPeerInstanceConfiguration); + } + } + + } + + private Optional getOptionalPassword(final Rfc2385Key password) { + return password != null && ! password.getValue().isEmpty() ? Optional.of(password) : Optional.absent(); + } + +} \ No newline at end of file