<artifactId>bgp-peer-acceptor</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-config-loader-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-config-loader-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-rib-mock</artifactId>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2016 Cisco Systems, Inc. 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/bgpcep.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/bgpcep.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/BGP_LS_PCEP:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+ <parent>
+ <artifactId>bgp-parent</artifactId>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <version>0.7.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>bgp-config-loader-impl</artifactId>
+ <description>BGP Initial configuration Loader</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-config-loader-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-codec-xml</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <!--
+ Maven Site Configuration
+
+ The following configuration is necessary for maven-site-plugin to
+ correctly identify the correct deployment path for OpenDaylight Maven
+ sites.
+ -->
+ <url>${odl.site.url}/${project.groupId}/${stream}/${project.artifactId}/</url>
+ <distributionManagement>
+ <site>
+ <id>opendaylight-site</id>
+ <url>${nexus.site.url}/${project.artifactId}/</url>
+ </site>
+ </distributionManagement>
+</project>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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.protocol.bgp.config.loader.impl;
+
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
+
+import com.google.common.base.Preconditions;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.GuardedBy;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+import org.opendaylight.protocol.bgp.config.loader.spi.ConfigFileProcessor;
+import org.opendaylight.protocol.bgp.config.loader.spi.ConfigLoader;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.yangtools.concepts.AbstractRegistration;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ConfigLoaderImpl implements ConfigLoader, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigLoaderImpl.class);
+ private static final String DEFAULT_APP_CONFIG_FILE_PATH = "etc" + File.separator + "opendaylight" + File.separator + "bgp";
+ private static final String INTERRUPTED = "InterruptedException";
+ private static final String EXTENSION = "-.*\\.xml";
+ private static final String INITIAL = "^";
+ private static final Path PATH = Paths.get(DEFAULT_APP_CONFIG_FILE_PATH);
+ @GuardedBy("this")
+ private final Map<String, ConfigFileProcessor> configServices = new HashMap<>();
+ private final SchemaContext schemaContext;
+ private final Thread watcherThread;
+ private final BindingNormalizedNodeSerializer bindingSerializer;
+
+ public ConfigLoaderImpl(final SchemaContext schemaContext, final BindingNormalizedNodeSerializer bindingSerializer) {
+ this.schemaContext = Preconditions.checkNotNull(schemaContext);
+ this.bindingSerializer = Preconditions.checkNotNull(bindingSerializer);
+ this.watcherThread = new Thread(new Watcher());
+ this.watcherThread.start();
+ LOG.info("Config Loader service initiated");
+ }
+
+ private class Watcher implements Runnable {
+ @Override
+ public void run() {
+ WatchKey key;
+ try {
+ while (!Thread.currentThread().isInterrupted()) {
+ final WatchService watcher = FileSystems.getDefault().newWatchService();
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ try {
+ watcher.close();
+ } catch (final IOException e) {
+ LOG.warn(INTERRUPTED, e);
+ }
+ }
+ });
+
+ PATH.register(watcher, OVERFLOW, ENTRY_CREATE);
+ key = watcher.take();
+ key.pollEvents().forEach(event -> handleEvent(event.context().toString()));
+
+ final boolean reset = key.reset();
+ if (!reset) {
+ LOG.warn("Could not reset the watch key.");
+ break;
+ }
+ }
+ } catch (final Exception e) {
+ LOG.warn(INTERRUPTED, e);
+ }
+ }
+ }
+
+ private void handleConfigFile(final ConfigFileProcessor config, final String filename) {
+ final NormalizedNode<?, ?> dto;
+ try {
+ dto = parseDefaultConfigFile(config, filename);
+ } catch (final Exception e) {
+ LOG.warn("Failed to parse config file {}", filename, e);
+ return;
+ }
+ LOG.info("Loading initial config {}", filename);
+ config.loadConfiguration(dto);
+ }
+
+ private NormalizedNode<?, ?> parseDefaultConfigFile(final ConfigFileProcessor config, final String filename) throws Exception {
+ final NormalizedNodeResult result = new NormalizedNodeResult();
+ final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+
+ final InputStream resourceAsStream = new FileInputStream(new File(DEFAULT_APP_CONFIG_FILE_PATH, filename));
+ final XMLInputFactory factory = XMLInputFactory.newInstance();
+ final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
+
+ final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, this.schemaContext,
+ SchemaContextUtil.findDataSchemaNode(this.schemaContext, config.getSchemaPath()));
+ xmlParser.parse(reader);
+
+ return result.getResult();
+ }
+
+ public synchronized AbstractRegistration registerConfigFile(@Nonnull final ConfigFileProcessor config) {
+ final String pattern = INITIAL + config.getSchemaPath().getLastComponent().getLocalName() + EXTENSION;
+ configServices.put(pattern, config);
+
+ final File[] fList = new File(DEFAULT_APP_CONFIG_FILE_PATH).listFiles();
+ if (fList != null) {
+ for (final File file : fList) {
+ if (file.isFile()) {
+ final String filename = file.getName();
+ if (Pattern.matches(pattern, filename)) {
+ handleConfigFile(config, filename);
+ }
+ }
+ }
+ }
+
+ return new AbstractRegistration() {
+ @Override
+ protected void removeRegistration() {
+ synchronized (ConfigLoaderImpl.this) {
+ ConfigLoaderImpl.this.configServices.remove(pattern);
+ }
+ }
+ };
+ }
+
+ @Override
+ public BindingNormalizedNodeSerializer getBindingNormalizedNodeSerializer() {
+ return this.bindingSerializer;
+ }
+
+ private synchronized void handleEvent(final String filename) {
+ configServices.entrySet().stream().filter(entry -> Pattern.matches(entry.getKey(), filename)).
+ forEach(entry -> handleConfigFile(entry.getValue(), filename));
+ }
+
+ @Override
+ public void close() throws Exception {
+ this.watcherThread.interrupt();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0">
+ <odl:static-reference id="schemaService" interface="org.opendaylight.controller.sal.core.api.model.SchemaService" />
+ <odl:static-reference id="binding-codec" interface="org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer" />
+
+ <bean id="bgpConfigLoader" class="org.opendaylight.protocol.bgp.config.loader.impl.ConfigLoaderImpl" destroy-method="close">
+ <argument>
+ <bean factory-ref="schemaService" factory-method="getGlobalContext"/>
+ </argument>
+ <argument ref="binding-codec"/>
+ </bean>
+
+ <service ref="bgpConfigLoader" interface="org.opendaylight.protocol.bgp.config.loader.spi.ConfigLoader" odl:type="default"/>
+</blueprint>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/bgpcep.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/bgpcep.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/BGP_LS_PCEP:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+ <parent>
+ <artifactId>bgp-parent</artifactId>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <version>0.7.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>bgp-config-loader-spi</artifactId>
+ <description>BGP Initial configuration Loader SPI</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-binding-dom-codec</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <!--
+ Maven Site Configuration
+
+ The following configuration is necessary for maven-site-plugin to
+ correctly identify the correct deployment path for OpenDaylight Maven
+ sites.
+ -->
+ <url>${odl.site.url}/${project.groupId}/${stream}/${project.artifactId}/</url>
+ <distributionManagement>
+ <site>
+ <id>opendaylight-site</id>
+ <url>${nexus.site.url}/${project.artifactId}/</url>
+ </site>
+ </distributionManagement>
+</project>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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.protocol.bgp.config.loader.spi;
+
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+/**
+ * Takes care of obtain object schema, schema Qname is used as base to create a pattern
+ * (Qname + "-" + * + ".xml") to recognize which files needs to be processed by each
+ * e.g. ProtocolsConfigFileProcessor will process any file containing the naming protocols-*.xml
+ */
+public interface ConfigFileProcessor {
+
+ /**
+ * Schema Path to search for
+ *
+ * @return SchemaPath
+ */
+ SchemaPath getSchemaPath();
+
+ /**
+ * Load the information contained on the normalized node
+ *
+ * @param dto normalizedNode
+ */
+ void loadConfiguration(@Nonnull NormalizedNode<?, ?> dto);
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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.protocol.bgp.config.loader.spi;
+
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.yangtools.concepts.AbstractRegistration;
+
+public interface ConfigLoader {
+ /**
+ * Register object model handler
+ * @param config Config File Processor
+ */
+ AbstractRegistration registerConfigFile(@Nonnull ConfigFileProcessor config);
+
+ /**
+ *
+ * @return Binding Normalized node serializer
+ */
+ BindingNormalizedNodeSerializer getBindingNormalizedNodeSerializer();
+}
<type>xml</type>
<classifier>bmp-config-example</classifier>
</artifact>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/protocols-config.xml</file>
+ <type>xml</type>
+ <classifier>bgp-initial-config</classifier>
+ </artifact>
</artifacts>
</configuration>
</execution>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2016 Cisco Systems, Inc. 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
+-->
+<protocols xmlns="http://openconfig.net/yang/network-instance">
+ <protocol xmlns="http://openconfig.net/yang/network-instance">
+ <name>bgp-example</name>
+ <identifier xmlns:x="http://openconfig.net/yang/policy-types">x:BGP</identifier>
+ <bgp xmlns="urn:opendaylight:params:xml:ns:yang:bgp:openconfig-extensions">
+ <global>
+ <config>
+ <router-id>192.0.2.2</router-id>
+ <as>64496</as>
+ <!-- if cluster-id is not present, it's value is the same as bgp-id -->
+ <!-- <route-reflector-cluster-id>192.0.2.3</route-reflector-cluster-id> -->
+ </config>
+ <afi-safis>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:IPV4-UNICAST</afi-safi-name>
+ <!--Advertise N Paths
+ <receive>true</receive>
+ <send-max>2</send-max>-->
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:IPV6-UNICAST</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:IPV4-LABELLED-UNICAST</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:IPV6-LABELLED-UNICAST</afi-safi-name>
+ </afi-safi>
+
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:L3VPN-IPV4-UNICAST</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:L3VPN-IPV6-UNICAST</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:L2VPN-EVPN</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>LINKSTATE</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>IPV4-FLOW</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>IPV6-FLOW</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>IPV4-L3VPN-FLOW</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>IPV6-L3VPN-FLOW</afi-safi-name>
+ </afi-safi>
+ </afi-safis>
+ </global>
+ <neighbors xmlns="urn:opendaylight:params:xml:ns:yang:bgp:openconfig-extensions">
+ <neighbor xmlns="urn:opendaylight:params:xml:ns:yang:bgp:openconfig-extensions">
+ <neighbor-address>192.0.2.1</neighbor-address>
+ <config>
+ <peer-type>INTERNAL</peer-type>
+ <peer-as>64496</peer-as>
+ </config>
+ <transport>
+ <config>
+ <remote-port>179</remote-port>
+ <passive-mode>true</passive-mode>
+ </config>
+ </transport>
+ <timers>
+ <config>
+ <hold-time>180</hold-time>
+ <connect-retry>10</connect-retry>
+ </config>
+ </timers>
+ <route-reflector>
+ <config>
+ <route-reflector-client>false</route-reflector-client>
+ </config>
+ </route-reflector>
+ <afi-safis>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:IPV4-UNICAST</afi-safi-name>
+ <!--Advertise N Paths
+ <receive>true</receive>
+ <send-max>0</send-max>-->
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:IPV6-UNICAST</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:IPV4-LABELLED-UNICAST</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:IPV6-LABELLED-UNICAST</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:L3VPN-IPV4-UNICAST</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:L3VPN-IPV6-UNICAST</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name xmlns:x="http://openconfig.net/yang/bgp-types">x:L2VPN-EVPN</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>LINKSTATE</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>IPV4-FLOW</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>IPV6-FLOW</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>IPV4-L3VPN-FLOW</afi-safi-name>
+ </afi-safi>
+ <afi-safi>
+ <afi-safi-name>IPV6-L3VPN-FLOW</afi-safi-name>
+ </afi-safi>
+ </afi-safis>
+ </neighbor>
+ <neighbor xmlns="urn:opendaylight:params:xml:ns:yang:bgp:openconfig-extensions">
+ <neighbor-address>192.0.2.6</neighbor-address>
+ <config>
+ <peer-group>application-peers</peer-group>
+ </config>
+ </neighbor>
+ </neighbors>
+ </bgp>
+ </protocol>
+</protocols>
\ No newline at end of file
final Map<BgpTableType, PathSelectionMode> pathSelectionModes = new HashMap<>();
for (final AfiSafi afiSafi : afiSafis) {
final BgpNeighborAddPathsConfig afiSafi2 = afiSafi.getAugmentation(AfiSafi2.class);
- final Optional<BgpTableType> bgpTableType = OpenConfigUtil.toBgpTableType(afiSafi.getAfiSafiName());
- if (afiSafi2 != null && bgpTableType.isPresent()) {
- final Short sendMax = afiSafi2.getSendMax();
- final PathSelectionMode selectionMode;
- if (sendMax > 1) {
- selectionMode = new AddPathBestNPathSelection(sendMax.longValue());
- } else {
- selectionMode = new AllPathSelection();
+ if (afiSafi2 != null) {
+ final Optional<BgpTableType> bgpTableType = OpenConfigUtil.toBgpTableType(afiSafi.getAfiSafiName());
+ if (bgpTableType.isPresent()) {
+ final Short sendMax = afiSafi2.getSendMax();
+ final PathSelectionMode selectionMode;
+ if (sendMax > 1) {
+ selectionMode = new AddPathBestNPathSelection(sendMax.longValue());
+ } else {
+ selectionMode = new AllPathSelection();
+ }
+ pathSelectionModes.put(bgpTableType.get(), selectionMode);
}
- pathSelectionModes.put(bgpTableType.get(), selectionMode);
}
}
return pathSelectionModes;
<module>evpn</module>
<module>cli</module>
<module>peer-acceptor</module>
+ <module>config-loader-spi</module>
+ <module>config-loader-impl</module>
</modules>
<!--
</properties>
<dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>concepts</artifactId>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>util</artifactId>
- </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-concepts</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>bgp-parser-api</artifactId>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>bgp-parser-spi</artifactId>
+ <artifactId>bgp-rib-spi</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>bgp-rib-api</artifactId>
+ <artifactId>bgp-config-loader-spi</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>bgp-rib-spi</artifactId>
+ <artifactId>bgp-openconfig-spi</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>bgp-rib-spi</artifactId>
- <type>test-jar</type>
- <scope>test</scope>
+ <artifactId>bgp-path-selection-mode</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>testtool-util</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-codec</artifactId>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-buffer</artifactId>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-common</artifactId>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-transport-native-epoll</artifactId>
- <classifier>${os.detected.classifier}</classifier>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.mdsal</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>concepts</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-model-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-impl</artifactId>
+ <artifactId>bgp-inet</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-parser-impl</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-api</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-config</artifactId>
<artifactId>mdsal-binding-generator-impl</artifactId>
</dependency>
<dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netty-config-api</artifactId>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+
+ <!--Netty -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netty-timer-config</artifactId>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>bgp-openconfig-spi</artifactId>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-codec</artifactId>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>bgp-openconfig-api</artifactId>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-transport-native-epoll</artifactId>
+ <classifier>${os.detected.classifier}</classifier>
</dependency>
+ <!-- Testing dependencies -->
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>bgp-path-selection-mode</artifactId>
+ <artifactId>bgp-rib-spi</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>bgp-inet</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
+ <artifactId>testtool-util</artifactId>
+ <scope>test</scope>
</dependency>
- <!-- Testing dependencies -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-path-selection-mode</artifactId>
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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.protocol.bgp.rib.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.opendaylight.protocol.bgp.config.loader.spi.ConfigFileProcessor;
+import org.opendaylight.protocol.bgp.config.loader.spi.ConfigLoader;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BgpDeployer;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Neighbors;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.NetworkInstances;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.NetworkInstance;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.Protocols;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.Protocol;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.ProtocolKey;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.policy.types.rev151009.BGP;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.Protocol1;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.yangtools.concepts.AbstractRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public final class ProtocolsConfigFileProcessor implements ConfigFileProcessor, AutoCloseable {
+ private final BindingNormalizedNodeSerializer bindingSerializer;
+ private final BgpDeployer bgpDeployer;
+ private final AbstractRegistration registration;
+ private final InstanceIdentifier<Protocols> protocolsIID;
+ private final YangInstanceIdentifier protocolYIId;
+ private static final SchemaPath PROTOCOLS_SCHEMA_PATH = SchemaPath.create(true, NetworkInstances.QNAME, NetworkInstance.QNAME,Protocols.QNAME);
+
+ public ProtocolsConfigFileProcessor(final ConfigLoader configLoader, final BgpDeployer bgpDeployer) {
+ Preconditions.checkNotNull(configLoader);
+ this.bgpDeployer = Preconditions.checkNotNull(bgpDeployer);
+ this.protocolsIID = this.bgpDeployer.getInstanceIdentifier().child(Protocols.class);
+ this.bindingSerializer = configLoader.getBindingNormalizedNodeSerializer();
+ this.registration = configLoader.registerConfigFile(this);
+ this.protocolYIId = this.bindingSerializer.toYangInstanceIdentifier(this.protocolsIID.child(Protocol.class));
+ }
+
+ @Override
+ public SchemaPath getSchemaPath() {
+ return PROTOCOLS_SCHEMA_PATH;
+ }
+
+ @Override
+ public void loadConfiguration(@Nonnull final NormalizedNode<?, ?> dto) {
+ final Collection<MapEntryNode> protocolsCollection = ((MapNode) dto).getValue();
+ for (final MapEntryNode protocolEntry : protocolsCollection) {
+ final Map.Entry<InstanceIdentifier<?>, DataObject> bi = this.bindingSerializer.fromNormalizedNode(this.protocolYIId, protocolEntry);
+ if (bi != null) {
+ notifyDeployer((Protocol) bi.getValue());
+ }
+ }
+ }
+
+ private void notifyDeployer(final Protocol protocol) {
+ final Protocol1 bgp = protocol.getAugmentation(Protocol1.class);
+ if (bgp != null) {
+ final InstanceIdentifier<Bgp> bgpIID = this.protocolsIID.child(Protocol.class, new ProtocolKey(BGP.class, protocol.getName()))
+ .augmentation(Protocol1.class).child(Bgp.class);
+
+ final Global global = bgp.getBgp().getGlobal();
+ if (global != null) {
+ this.bgpDeployer.onGlobalModified(bgpIID, global, () -> this.bgpDeployer.writeConfiguration(global, bgpIID.child(Global.class)));
+ }
+
+ final Neighbors neighbors = bgp.getBgp().getNeighbors();
+ if (neighbors != null) {
+ final List<Neighbor> neighborsList = neighbors.getNeighbor();
+ final InstanceIdentifier<Neighbors> neighborsIID = bgpIID.child(Neighbors.class);
+ neighborsList.forEach(neighbor -> this.bgpDeployer.onNeighborModified(bgpIID, neighbor,
+ () -> this.bgpDeployer.writeConfiguration(neighbor, neighborsIID.child(Neighbor.class, neighbor.getKey()))));
+ }
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ this.registration.close();
+ }
+}
<reference id="globalWorkerGroup" interface="io.netty.channel.EventLoopGroup" odl:type="global-worker-group"/>
<reference id="clusterSingletonServiceProvider" interface="org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider"/>
- <bean id="BGPDispatcher" class="org.opendaylight.protocol.bgp.rib.impl.BGPDispatcherImpl">
+ <bean id="BGPDispatcher" class="org.opendaylight.protocol.bgp.rib.impl.BGPDispatcherImpl" destroy-method="close">
<argument>
<bean factory-ref="BGPExtensionContext" factory-method="getMessageRegistry"/>
</argument>
</service>
<bean id="BGPPeerRegistry" class="org.opendaylight.protocol.bgp.rib.impl.StrictBGPPeerRegistry"
- factory-method="instance"/>
+ factory-method="instance" destroy-method="close"/>
<service ref="BGPPeerRegistry" interface="org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry"
odl:type="default">
<reference id="schemaService" interface="org.opendaylight.controller.sal.core.api.model.SchemaService"/>
<reference id="rpcRegistry" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"/>
- <bean id="bgpDeployer" class="org.opendaylight.protocol.bgp.rib.impl.config.BgpDeployerImpl">
+ <bean id="bgpDeployer" class="org.opendaylight.protocol.bgp.rib.impl.config.BgpDeployerImpl" destroy-method="close">
<argument value="global-bgp"/>
<argument ref="blueprintContainer"/>
<argument ref="blueprintBundleContext"/>
<bean id="appPeer" class="org.opendaylight.protocol.bgp.rib.impl.config.AppPeer" scope="prototype"/>
+ <reference id="bgpConfigLoader" interface="org.opendaylight.protocol.bgp.config.loader.spi.ConfigLoader"/>
+
+ <bean id="protocolsInitialConfig" class="org.opendaylight.protocol.bgp.rib.impl.ProtocolsConfigFileProcessor" destroy-method="close">
+ <argument ref="bgpConfigLoader"/>
+ <argument ref="bgpDeployer"/>
+ </bean>
</blueprint>
\ No newline at end of file
<yangtools.version>1.1.0-SNAPSHOT</yangtools.version>
<mdsal.version>1.5.0-SNAPSHOT</mdsal.version>
<mdsal.model.version>0.10.0-SNAPSHOT</mdsal.model.version>
+ <mdsal.common.version>2.2.0-SNAPSHOT</mdsal.common.version>
<config.version>0.6.0-SNAPSHOT</config.version>
<odlparent.version>1.8.0-SNAPSHOT</odlparent.version>
</properties>
<dependency>
<groupId>org.opendaylight.mdsal</groupId>
<artifactId>features-mdsal</artifactId>
- <version>2.2.0-SNAPSHOT</version>
+ <version>${mdsal.common.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<version>${mdsal.model.version}</version>
<classifier>features</classifier>
<type>xml</type>
- <scope>runtime</scope>
+ <scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.opendaylight.bgpcep</groupId>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-peer-acceptor</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-config-loader-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-config-loader-impl</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-controller-config</artifactId>
<feature version='${project.version}'>odl-bgpcep-bgp-cli</feature>
<configfile finalname="etc/opendaylight/karaf/31-bgp.xml">mvn:org.opendaylight.bgpcep/bgp-controller-config/{{VERSION}}/xml/config</configfile>
<configfile finalname="etc/opendaylight/karaf/41-bgp-example.xml">mvn:org.opendaylight.bgpcep/bgp-controller-config/{{VERSION}}/xml/config-example</configfile>
+ <configfile finalname="etc/opendaylight/bgp/protocols-config.xml">mvn:org.opendaylight.bgpcep/bgp-controller-config/{{VERSION}}/xml/bgp-initial-config</configfile>
</feature>
<feature name="odl-bgpcep-bgp-openconfig" version='${project.version}'>
<feature version='${project.version}'>odl-bgpcep-bgp-rib-api</feature>
<feature version='${project.version}'>odl-bgpcep-bgp-inet</feature>
<feature version='${project.version}'>odl-bgpcep-bgp-path-selection-mode</feature>
+ <feature version='${project.version}'>odl-bgpcep-bgp-config-loader</feature>
<bundle>mvn:org.opendaylight.bgpcep/bgp-openconfig-api/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.bgpcep/bgp-openconfig-spi/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.bgpcep/bgp-rib-impl/{{VERSION}}</bundle>
<feature version='${project.version}'>odl-bgpcep-bgp-rib-impl</feature>
<bundle>mvn:org.opendaylight.bgpcep/bgp-cli/{{VERSION}}</bundle>
</feature>
+
+ <feature name="odl-bgpcep-bgp-config-loader" version='${project.version}'>
+ <feature version='${mdsal.common.version}'>odl-mdsal-binding-runtime</feature>
+ <bundle>mvn:org.opendaylight.bgpcep/bgp-config-loader-spi/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.bgpcep/bgp-config-loader-impl/{{VERSION}}</bundle>
+ </feature>
</features>