<properties>
<odl.karaf.base.version>1.6.0-SNAPSHOT</odl.karaf.base.version>
<mdsal.version>1.3.0-SNAPSHOT</mdsal.version>
+ <mdsal.model.version>0.8.0-SNAPSHOT</mdsal.model.version>
+ <restconf.version>1.3.0-SNAPSHOT</restconf.version>
<neutron.version>0.6.0-SNAPSHOT</neutron.version>
<openflowplugin.version>0.2.0-SNAPSHOT</openflowplugin.version>
<yangtools.version>0.8.0-SNAPSHOT</yangtools.version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>features-mdsal-model</artifactId>
+ <version>${mdsal.model.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>features-restconf</artifactId>
+ <version>${restconf.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
<!-- external dependencies -->
<!-- TODO clean up based on what is provided by odlparent -->
<dependency>
<type>xml</type>
<classifier>features</classifier>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netvirt-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>hwgw</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>hwvtepsouthbound-features</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
<!-- DLUX dependency for the UI -->
<dependency>
<groupId>org.opendaylight.dlux</groupId>
<repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository>
<repository>mvn:org.opendaylight.ovsdb/library-features/{{VERSION}}/xml/features</repository>
<repository>mvn:org.opendaylight.dlux/features-dlux/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.netconf/features-restconf/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.ovsdb/hwvtepsouthbound-features/{{VERSION}}/xml/features</repository>
<feature name="odl-ovsdb-all" description="OpenDaylight :: OVSDB :: all"
version='${project.version}'>
<feature version="${dlux.version}">odl-dlux-core</feature>
<bundle>mvn:org.opendaylight.ovsdb/ovsdb-ui-bundle/{{VERSION}}</bundle>
</feature>
+ <feature name='odl-netvirt-api' version='${project.version}' description='OpenDaylight :: netvirt :: api'>
+ <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+ <bundle>mvn:org.opendaylight.ovsdb/netvirt-api/{{VERSION}}</bundle>
+ </feature>
+ <feature name='odl-netvirt-rest' version='${project.version}' description='OpenDaylight :: netvirt :: REST'>
+ <feature version="${project.version}">odl-netvirt-api</feature>
+ <feature version="${restconf.version}">odl-restconf</feature>
+ </feature>
+ <feature name='odl-netvirt-ui' version='${project.version}' description='OpenDaylight :: netvirt :: UI'>
+ <feature version="${project.version}">odl-netvirt-rest</feature>
+ <feature version="${restconf.version}">odl-mdsal-apidocs</feature>
+ <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
+ </feature>
+ <feature name='odl-netvirt-hwgw' version='${project.version}' description='OpenDaylight :: netvirt :: Hardware Gateway'>
+ <feature version="${project.version}">odl-netvirt-api</feature>
+ <feature version='${project.version}'>odl-ovsdb-hwvtepsouthbound</feature>
+ <bundle>mvn:org.opendaylight.ovsdb/hwgw/{{VERSION}}</bundle>
+ </feature>
+
</features>
namespace "urn:opendaylight:params:xml:ns:yang:netvirt";
prefix "netvirt";
- revision "2015-01-05" {
+ revision "2015-12-27" {
description "Initial revision of netvirt model";
}
}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (c) 2015 Red Hat, 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">
-
- <parent>
- <groupId>org.opendaylight.odlparent</groupId>
- <artifactId>odlparent-lite</artifactId>
- <version>1.6.0-SNAPSHOT</version>
- <relativePath/>
- </parent>
-
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.opendaylight.ovsdb</groupId>
- <artifactId>netvirt-artifacts</artifactId>
- <version>1.2.1-SNAPSHOT</version>
- <packaging>pom</packaging>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netvirt-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netvirt-impl</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netvirt-features</artifactId>
- <version>${project.version}</version>
- <classifier>features</classifier>
- <type>xml</type>
- </dependency>
- </dependencies>
- </dependencyManagement>
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (c) 2015 Red Hat, 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 INTERNAL
--->
-<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">
- <parent>
- <groupId>org.opendaylight.odlparent</groupId>
- <artifactId>features-parent</artifactId>
- <version>1.6.0-SNAPSHOT</version>
- <relativePath/>
- </parent>
-
- <groupId>org.opendaylight.ovsdb</groupId>
- <artifactId>netvirt-features</artifactId>
- <version>1.2.1-SNAPSHOT</version>
- <name>${project.artifactId}</name>
- <modelVersion>4.0.0</modelVersion>
- <prerequisites>
- <maven>3.1.1</maven>
- </prerequisites>
-
- <properties>
- <configfile.directory>etc/opendaylight/karaf</configfile.directory>
- <mdsal.version>1.3.0-SNAPSHOT</mdsal.version>
- <mdsal.model.version>0.8.0-SNAPSHOT</mdsal.model.version>
- <restconf.version>1.3.0-SNAPSHOT</restconf.version>
- <yangtools.version>0.8.0-SNAPSHOT</yangtools.version>
- </properties>
- <dependencyManagement>
- <dependencies>
- <!-- project specific dependencies -->
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yangtools-artifacts</artifactId>
- <version>${yangtools.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>mdsal-artifacts</artifactId>
- <version>${mdsal.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.netconf</groupId>
- <artifactId>restconf-artifacts</artifactId>
- <version>${restconf.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>features-yangtools</artifactId>
- <classifier>features</classifier>
- <version>${yangtools.version}</version>
- <type>xml</type>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.mdsal.model</groupId>
- <artifactId>features-mdsal-model</artifactId>
- <version>${mdsal.model.version}</version>
- <classifier>features</classifier>
- <type>xml</type>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.netconf</groupId>
- <artifactId>features-restconf</artifactId>
- <classifier>features</classifier>
- <version>${restconf.version}</version>
- <type>xml</type>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>features-mdsal</artifactId>
- <classifier>features</classifier>
- <type>xml</type>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netvirt-impl</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netvirt-impl</artifactId>
- <version>${project.version}</version>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netvirt-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- </dependencies>
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
-Copyright (c) 2015 Red Hat, Inc.
-
-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
--->
-<features name="odl-netvirt-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
- <repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository>
- <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/{{VERSION}}/xml/features</repository>
- <repository>mvn:org.opendaylight.netconf/features-restconf/{{VERSION}}/xml/features</repository>
- <feature name='odl-netvirt-api' version='${project.version}' description='OpenDaylight :: netvirt :: api'>
- <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
- <bundle>mvn:org.opendaylight.ovsdb/netvirt-api/{{VERSION}}</bundle>
- </feature>
- <feature name='odl-netvirt' version='${project.version}' description='OpenDaylight :: netvirt'>
- <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
- <feature version='${project.version}'>odl-netvirt-api</feature>
- <bundle>mvn:org.opendaylight.ovsdb/netvirt-impl/{{VERSION}}</bundle>
- <configfile finalname="${configfile.directory}/netvirt.xml">mvn:org.opendaylight.ovsdb/netvirt-impl/{{VERSION}}/xml/config</configfile>
- </feature>
- <feature name='odl-netvirt-rest' version='${project.version}' description='OpenDaylight :: netvirt :: REST'>
- <feature version="${project.version}">odl-netvirt</feature>
- <feature version="${restconf.version}">odl-restconf</feature>
- </feature>
- <feature name='odl-netvirt-ui' version='${project.version}' description='OpenDaylight :: netvirt :: UI'>
- <feature version="${project.version}">odl-netvirt-rest</feature>
- <feature version="${restconf.version}">odl-mdsal-apidocs</feature>
- <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
- </feature>
-
-</features>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
-Copyright (c) 2015 Red Hat, 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 INTERNAL
--->
-<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">
-
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-parent</artifactId>
- <version>0.4.0-SNAPSHOT</version>
- <relativePath/>
- </parent>
-
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.opendaylight.ovsdb</groupId>
- <artifactId>netvirt-impl</artifactId>
- <version>1.2.1-SNAPSHOT</version>
- <packaging>bundle</packaging>
- <dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netvirt-api</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <!-- Testing Dependencies -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
-Copyright (c) 2015 Red Hat, 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
--->
-<snapshot>
- <required-capabilities>
- <capability>urn:opendaylight:params:xml:ns:yang:netvirt:impl?module=netvirt-impl&revision=2014-12-10</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
- </required-capabilities>
- <configuration>
-
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:netvirt:impl">prefix:netvirt</type>
- <name>netvirt-default</name>
- <broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
- <name>binding-osgi-broker</name>
- </broker>
- </module>
- </modules>
- </data>
- </configuration>
-</snapshot>
+++ /dev/null
-/*
- * Copyright (c) 2015 Red Hat, 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.ovsdb.netvirt.impl;
-
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NetvirtProvider implements BindingAwareProvider, AutoCloseable {
-
- private static final Logger LOG = LoggerFactory.getLogger(NetvirtProvider.class);
-
- @Override
- public void onSessionInitiated(ProviderContext session) {
- LOG.info("NetvirtProvider Session Initiated");
- }
-
- @Override
- public void close() throws Exception {
- LOG.info("NetvirtProvider Closed");
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2015 Red Hat, 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.impl.rev141210;
-
-import org.opendaylight.ovsdb.netvirt.impl.NetvirtProvider;
-
-public class NetvirtModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.impl.rev141210.AbstractNetvirtModule {
- public NetvirtModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public NetvirtModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.impl.rev141210.NetvirtModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- NetvirtProvider provider = new NetvirtProvider();
- getBrokerDependency().registerProvider(provider);
- return provider;
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2015 Red Hat, 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
- */
-/*
-* Generated file
-*
-* Generated from: yang module name: netvirt yang module local name: netvirt
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Jan 02 13:49:24 CST 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.impl.rev141210;
-public class NetvirtModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.impl.rev141210.AbstractNetvirtModuleFactory {
-
-}
+++ /dev/null
-module netvirt-impl {
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:netvirt:impl";
- prefix "netvirt-impl";
-
- import config { prefix config; revision-date 2013-04-05; }
- import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
-
- description
- "Service definition for netvirt project";
-
- revision "2014-12-10" {
- description
- "Initial revision";
- }
-
- identity netvirt {
- base config:module-type;
- config:java-name-prefix Netvirt;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case netvirt {
- when "/config:modules/config:module/config:type = 'netvirt'";
- container broker {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity md-sal-binding:binding-broker-osgi-registry;
- }
- }
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2015 Red Hat, 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.ovsdb.netvirt.impl;
-
-import org.junit.Test;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-
-import static org.mockito.Mockito.mock;
-
-public class NetvirtProviderTest {
- @Test
- public void testOnSessionInitiated() {
- NetvirtProvider provider = new NetvirtProvider();
-
- // ensure no exceptions
- // currently this method is empty
- provider.onSessionInitiated(mock(BindingAwareBroker.ProviderContext.class));
- }
-
- @Test
- public void testClose() throws Exception {
- NetvirtProvider provider = new NetvirtProvider();
-
- // ensure no exceptions
- // currently this method is empty
- provider.close();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2015 Red Hat, 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.impl.rev141210;
-
-import org.junit.Test;
-
-public class NetvirtModuleFactoryTest {
- @Test
- public void testFactoryConstructor() {
- // ensure no exceptions on construction
- new NetvirtModuleFactory();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2015 Red Hat, 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.impl.rev141210;
-
-import org.junit.Test;
-import org.opendaylight.controller.config.api.DependencyResolver;
-import org.opendaylight.controller.config.api.JmxAttribute;
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.ovsdb.netvirt.impl.NetvirtProvider;
-
-import javax.management.ObjectName;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class NetvirtModuleTest {
- @Test
- public void testCustomValidation() {
- NetvirtModule module = new NetvirtModule(mock(ModuleIdentifier.class), mock(DependencyResolver.class));
-
- // ensure no exceptions on validation
- // currently this method is empty
- module.customValidation();
- }
-
- @Test
- public void testCreateInstance() throws Exception {
- // configure mocks
- DependencyResolver dependencyResolver = mock(DependencyResolver.class);
- BindingAwareBroker broker = mock(BindingAwareBroker.class);
- when(dependencyResolver.resolveInstance(eq(BindingAwareBroker.class), any(ObjectName.class), any(JmxAttribute.class))).thenReturn(broker);
-
- // create instance of module with injected mocks
- NetvirtModule module = new NetvirtModule(mock(ModuleIdentifier.class), dependencyResolver);
-
- // getInstance calls resolveInstance to get the broker dependency and then calls createInstance
- AutoCloseable closeable = module.getInstance();
-
- // verify that the module registered the returned provider with the broker
- verify(broker).registerProvider((NetvirtProvider)closeable);
-
- // ensure no exceptions on close
- closeable.close();
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (c) 2015 Red Hat, 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 INTERNAL
--->
-<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">
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>karaf-parent</artifactId>
- <version>1.6.0-SNAPSHOT</version>
- <relativePath/>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.opendaylight.ovsdb</groupId>
- <artifactId>netvirt-karaf</artifactId>
- <version>1.2.1-SNAPSHOT</version>
- <name>${project.artifactId}</name>
- <prerequisites>
- <maven>3.1.1</maven>
- </prerequisites>
- <properties>
- <karaf.localFeature>odl-netvirt-ui</karaf.localFeature>
- </properties>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netvirt-artifacts</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <dependencies>
- <dependency>
- <!-- scope is compile so all features (there is only one) are installed
- into startup.properties and the feature repo itself is not installed -->
- <groupId>org.apache.karaf.features</groupId>
- <artifactId>framework</artifactId>
- <type>kar</type>
- </dependency>
-
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netvirt-features</artifactId>
- <classifier>features</classifier>
- <type>xml</type>
- <scope>runtime</scope>
- </dependency>
- </dependencies>
- <!-- DO NOT install or deploy the karaf artifact -->
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-deploy-plugin</artifactId>
- <configuration>
- <skip>true</skip>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-install-plugin</artifactId>
- <configuration>
- <skip>true</skip>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
</prerequisites>
<modules>
<module>api</module>
- <module>impl</module>
- <module>karaf</module>
- <module>features</module>
- <module>artifacts</module>
<module>renderers</module>
</modules>
<!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
-->
<snapshot>
<required-capabilities>
- <capability>urn:opendaylight:params:xml:ns:yang:hwgw?module=hwgw&revision=2014-12-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:hwgw?module=hwgw&revision=2015-12-27</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
</required-capabilities>
<configuration>
+++ /dev/null
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev141210;
-public class HwgwModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev141210.AbstractHwgwModule {
- public HwgwModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public HwgwModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev141210.HwgwModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- // TODO:implement
- throw new java.lang.UnsupportedOperationException();
- }
-
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: hwgw yang module local name: hwgw
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Tue Dec 22 22:54:15 EST 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev141210;
-public class HwgwModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev141210.AbstractHwgwModuleFactory {
-
-}
* 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hwgw.rev141210;
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev151227;
import org.opendaylight.ovsdb.netvirt.renderers.hwgw.HwgwProvider;
-public class HwgwModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev141210.AbstractHwgwModule {
+public class HwgwModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev151227.AbstractHwgwModule {
public HwgwModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
super(identifier, dependencyResolver);
}
- public HwgwModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hwgw.rev141210.HwgwModule oldModule, java.lang.AutoCloseable oldInstance) {
+ public HwgwModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev151227.HwgwModule oldModule, java.lang.AutoCloseable oldInstance) {
super(identifier, dependencyResolver, oldModule, oldInstance);
}
*
* Do not modify this file unless it is present under src/main directory
*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hwgw.rev141210;
-public class HwgwModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev141210.AbstractHwgwModuleFactory {
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev151227;
+public class HwgwModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev151227.AbstractHwgwModuleFactory {
}
description
"Service definition for hwgw project";
- revision "2014-12-10" {
+ revision "2015-12-27" {
description
"Initial revision";
}
* 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hwgw.rev141210;
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev151227;
import org.junit.Test;
* 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hwgw.rev141210;
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.hwgw.rev151227;
import org.junit.Test;
import org.opendaylight.controller.config.api.DependencyResolver;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.UnknownHostException;
import java.util.ArrayList;
-import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.opendaylight.ovsdb.lib.notation.Version;
import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
-import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
-import org.opendaylight.ovsdb.southbound.SouthboundMapper;
-import org.opendaylight.ovsdb.utils.config.ConfigProperties;
import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
@ExamReactorStrategy(PerClass.class)
public class NetvirtIT extends AbstractMdsalTestBase {
private static final Logger LOG = LoggerFactory.getLogger(NetvirtIT.class);
- private static final int OVSDB_UPDATE_TIMEOUT = 1000;
private static DataBroker dataBroker = null;
private static String addressStr;
private static String portStr;
private static AtomicBoolean setup = new AtomicBoolean(false);
private static MdsalUtils mdsalUtils = null;
private static Southbound southbound = null;
+ private static PipelineOrchestrator pipelineOrchestrator = null;
private static SouthboundUtils southboundUtils;
private static NeutronUtils neutronUtils = new NeutronUtils();
private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
assertNotNull("southbound should not be null", southbound);
southboundUtils = new SouthboundUtils(mdsalUtils);
+ pipelineOrchestrator =
+ (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this);
+ assertNotNull("pipelineOrchestrator should not be null", pipelineOrchestrator);
setup.set(true);
}
return true;
}
+ // This is an extra test for local testing and testNetVirt covers this is more detail
+ @Ignore
@Test
public void testAddDeleteOvsdbNode() throws InterruptedException {
LOG.info("testAddDeleteOvsdbNode enter");
ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
- connectOvsdbNode(connectionInfo);
+ Node ovsdbNode = connectOvsdbNode(connectionInfo);
+ assertNotNull("connection failed", ovsdbNode);
+ LOG.info("testNetVirt: should be connected: {}", ovsdbNode.getNodeId());
assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo)
+ " is not connected", isControllerConnected(connectionInfo));
LOG.info("testAddDeleteOvsdbNode exit");
}
+ // TODO add tests for when L3 is enabled and check for br-ex
+
+ // This is an extra test for local testing and testNetVirt covers this is more detail
+ @Ignore
+ @Test
+ public void testAddDeleteOvsdbNodeWithTableOffset() throws InterruptedException {
+ LOG.info("testAddDeleteOvsdbNodeWithTableOffset enter");
+ NetvirtProvidersProvider.setTableOffset((short)1);
+ ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
+ Node ovsdbNode = connectOvsdbNode(connectionInfo);
+ assertNotNull("connection failed", ovsdbNode);
+ LOG.info("testNetVirt: should be connected: {}", ovsdbNode.getNodeId());
+
+ assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo)
+ + " is not connected", isControllerConnected(connectionInfo));
+
+ // Verify the pipeline flows were installed
+ Node bridgeNode = southbound.getBridgeNode(ovsdbNode, NetvirtITConstants.INTEGRATION_BRIDGE_NAME);
+ assertNotNull("bridge " + NetvirtITConstants.INTEGRATION_BRIDGE_NAME + " was not found", bridgeNode);
+ long datapathId = southbound.getDataPathId(bridgeNode);
+ String datapathIdString = southbound.getDatapathId(bridgeNode);
+ LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
+ assertNotEquals("datapathId was not found", datapathId, 0);
+
+ List<Service> staticPipeline = pipelineOrchestrator.getStaticPipeline();
+ List<Service> staticPipelineFound = Lists.newArrayList();
+ for (Service service : pipelineOrchestrator.getServiceRegistry().keySet()) {
+ if (staticPipeline.contains(service)) {
+ staticPipelineFound.add(service);
+ }
+ String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(service);
+ verifyFlow(datapathId, flowId, service);
+ }
+ assertEquals("did not find all expected flows in static pipeline",
+ staticPipeline.size(), staticPipelineFound.size());
+
+ String flowId = "TableOffset_" + pipelineOrchestrator.getTable(Service.CLASSIFIER);
+ verifyFlow(datapathId, flowId, Service.CLASSIFIER.getTable());
+
+ Assert.assertTrue(southboundUtils.deleteBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME));
+ Thread.sleep(1000);
+ Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
+ LOG.info("testAddDeleteOvsdbNodeWithTableOffset exit");
+ }
+
private boolean isControllerConnected(ConnectionInfo connectionInfo) throws InterruptedException {
LOG.info("isControllerConnected enter");
Boolean connected = false;
BridgeConfigurationManager bridgeConfigurationManager =
(BridgeConfigurationManager) ServiceHelper.getGlobalInstance(BridgeConfigurationManager.class, this);
- assertNotNull("Could not find PipelineOrchestrator Service", bridgeConfigurationManager);
+ assertNotNull("Could not find BridgeConfigurationManager Service", bridgeConfigurationManager);
String controllerTarget = bridgeConfigurationManager.getControllersFromOvsdbNode(ovsdbNode).get(0);
Assert.assertNotNull("Failed to get controller target", controllerTarget);
LOG.info("testNetVirt: starting test");
ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
Node ovsdbNode = connectOvsdbNode(connectionInfo);
- LOG.info("testNetVirt: should be connected");
+ assertNotNull("connection failed", ovsdbNode);
+ LOG.info("testNetVirt: should be connected: {}", ovsdbNode.getNodeId());
//TODO use controller value rather that ovsdb connectionInfo or change log
assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo)
+ " is not connected", isControllerConnected(connectionInfo));
// Verify the pipeline flows were installed
- PipelineOrchestrator pipelineOrchestrator =
- (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this);
- assertNotNull("Could not find PipelineOrchestrator Service", pipelineOrchestrator);
Node bridgeNode = southbound.getBridgeNode(ovsdbNode, NetvirtITConstants.INTEGRATION_BRIDGE_NAME);
assertNotNull("bridge " + NetvirtITConstants.INTEGRATION_BRIDGE_NAME + " was not found", bridgeNode);
- LOG.info("testNetVirt: bridgeNode: {}", bridgeNode);
long datapathId = southbound.getDataPathId(bridgeNode);
+ String datapathIdString = southbound.getDatapathId(bridgeNode);
+ LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
assertNotEquals("datapathId was not found", datapathId, 0);
List<Service> staticPipeline = pipelineOrchestrator.getStaticPipeline();
if (staticPipeline.contains(service)) {
staticPipelineFound.add(service);
}
- String flowId = "DEFAULT_PIPELINE_FLOW_" + service.getTable();
- verifyFlow(datapathId, flowId, service.getTable());
+ String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(service);
+ verifyFlow(datapathId, flowId, service);
}
assertEquals("did not find all expected flows in static pipeline",
staticPipeline.size(), staticPipelineFound.size());
OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
southbound.getTerminationPointOfBridge(bridgeNode, NetvirtITConstants.PORT_NAME);
Assert.assertNotNull("Did not find " + NetvirtITConstants.PORT_NAME, ovsdbTerminationPointAugmentation);
- Thread.sleep(1000);
Assert.assertTrue(southboundUtils.deleteBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME));
Thread.sleep(1000);
Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
final String dhcpPortId ="521e29d6-67b8-4b3c-8633-027d21195115";
ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
- assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
Node ovsdbNode = connectOvsdbNode(connectionInfo);
- assertNotNull("node is not connected", ovsdbNode);
+ assertNotNull("connection failed", ovsdbNode);
+ LOG.info("testNetVirtFixedSG: should be connected: {}", ovsdbNode.getNodeId());
// Verify the minimum version required for this test
OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
Node bridgeNode = southbound.getBridgeNode(ovsdbNode, NetvirtITConstants.INTEGRATION_BRIDGE_NAME);
assertNotNull("bridge " + NetvirtITConstants.INTEGRATION_BRIDGE_NAME + " was not found", bridgeNode);
long datapathId = southbound.getDataPathId(bridgeNode);
+ String datapathIdString = southbound.getDatapathId(bridgeNode);
+ LOG.info("testNetVirtFixedSG: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
assertNotEquals("datapathId was not found", datapathId, 0);
NeutronNetwork nn = neutronUtils.createNeutronNetwork(networkId, tenantId,
Thread.sleep(1000);
String flowId = "Egress_DHCP_Client" + "_Permit_";
- verifyFlow(datapathId, flowId, Service.EGRESS_ACL.getTable());
+ verifyFlow(datapathId, flowId, Service.EGRESS_ACL);
testDefaultSG(nport, datapathId, nn, tenantId, portId);
Thread.sleep(1000);
Thread.sleep(10000);
String flowId = "Egress_IP" + nn.getProviderSegmentationID() + "_" + nport.getMacAddress() + "_Permit_";
- verifyFlow(datapathId, flowId, Service.EGRESS_ACL.getTable());
+ verifyFlow(datapathId, flowId, Service.EGRESS_ACL);
flowId = "Ingress_IP" + nn.getProviderSegmentationID() + "_" + nport.getMacAddress() + "_Permit_";
- verifyFlow(datapathId, flowId, Service.INGRESS_ACL.getTable());
+ verifyFlow(datapathId, flowId, Service.INGRESS_ACL);
}
private Flow getFlow (
Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
assertNotNull("Could not find flow in config: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
- assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
+ assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(),
+ flow);
+ }
+
+ private void verifyFlow(long datapathId, String flowId, Service service) throws InterruptedException {
+ verifyFlow(datapathId, flowId, pipelineOrchestrator.getTable(service));
}
}
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:netvirt:providers:impl">prefix:netvirt-providers-impl</type>
<name>netvirt-providers-default</name>
+ <table-offset>0</table-offset>
<broker>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
<name>binding-osgi-broker</name>
import java.util.Hashtable;
import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.ovsdb.openstack.netvirt.api.*;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ClassifierProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
+import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolver;
+import org.opendaylight.ovsdb.openstack.netvirt.api.InboundNatProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.L2ForwardingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.L2RewriteProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.L3ForwardingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheListener;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.OutboundNatProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestratorImpl;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
-import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.*;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.ArpResponderService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.ClassifierService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.EgressAclService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.InboundNatService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.IngressAclService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.L2ForwardingService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.L2RewriteService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.L3ForwardingService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.LoadBalancerService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.OutboundNatService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.RoutingService;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.arp.GatewayMacResolverService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public void start(BundleContext context) throws Exception {
LOG.info("ConfigActivator start:");
+ NetvirtProvidersConfigImpl netvirtProvidersConfig =
+ new NetvirtProvidersConfigImpl(providerContext.getSALService(DataBroker.class),
+ NetvirtProvidersProvider.getTableOffset());
+ registerService(context,
+ new String[] {NetvirtProvidersConfigImpl.class.getName()},
+ null, netvirtProvidersConfig);
+
PipelineOrchestratorImpl pipelineOrchestrator = new PipelineOrchestratorImpl();
registerService(context,
new String[] {PipelineOrchestrator.class.getName(),NodeCacheListener.class.getName()},
registerService(context, OutboundNatProvider.class.getName(),
outboundNatService, Service.OUTBOUND_NAT);
- GatewayMacResolverService gatewayMacResolverService = new GatewayMacResolverService();
+ final GatewayMacResolverService gatewayMacResolverService = new GatewayMacResolverService();
registerService(context, GatewayMacResolver.class.getName(),
gatewayMacResolverService, Service.GATEWAY_RESOLVER);
getNotificationProviderService().registerNotificationListener(gatewayMacResolverService);
-
+ netvirtProvidersConfig.setDependencies(context, null);
pipelineOrchestrator.setDependencies(context, null);
outboundNatService.setDependencies(context, null);
egressAclService.setDependencies(context, null);
}
};
networkingProviderManagerTracker.open();
+
+ @SuppressWarnings("unchecked")
+ ServiceTracker ConfigurationServiceTracker = new ServiceTracker(context,
+ ConfigurationService.class, null) {
+ @Override
+ public Object addingService(ServiceReference reference) {
+ LOG.info("addingService ConfigurationService");
+ ConfigurationService service =
+ (ConfigurationService) context.getService(reference);
+ if (service != null) {
+ gatewayMacResolverService.setDependencies(service);
+ }
+ return service;
+ }
+ };
+ ConfigurationServiceTracker.open();
+
+ @SuppressWarnings("unchecked")
+ ServiceTracker NodeCacheManagerTracker = new ServiceTracker(context,
+ NodeCacheManager.class, null) {
+ @Override
+ public Object addingService(ServiceReference reference) {
+ LOG.info("addingService NodeCacheManager");
+ NodeCacheManager service =
+ (NodeCacheManager) context.getService(reference);
+ if (service != null) {
+ gatewayMacResolverService.setDependencies(service);
+ }
+ return service;
+ }
+ };
+ NodeCacheManagerTracker.open();
}
@Override
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, 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.ovsdb.openstack.netvirt.providers;
+
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
+import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbInventoryListener;
+import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetvirtProvidersConfigImpl implements AutoCloseable, ConfigInterface, DataChangeListener {
+ private static final Logger LOG = LoggerFactory.getLogger(NetvirtProvidersConfigImpl.class);
+ private final DataBroker dataBroker;
+ private final ListenerRegistration<DataChangeListener> registration;
+ private final ExecutorService executorService = Executors.newFixedThreadPool(1);
+ private final MdsalUtils mdsalUtils;
+
+ public NetvirtProvidersConfigImpl(final DataBroker dataBroker, final short tableOffset) {
+ this.dataBroker = dataBroker;
+ mdsalUtils = new MdsalUtils(dataBroker);
+
+ InstanceIdentifier<NetvirtProvidersConfig> path =
+ InstanceIdentifier.builder(NetvirtProvidersConfig.class).build();
+ registration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, this,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+
+ NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder = new NetvirtProvidersConfigBuilder();
+ NetvirtProvidersConfig netvirtProvidersConfig =
+ mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
+ if (netvirtProvidersConfig != null) {
+ netvirtProvidersConfigBuilder = new NetvirtProvidersConfigBuilder(netvirtProvidersConfig);
+ }
+ if (netvirtProvidersConfigBuilder.getTableOffset() == null) {
+ netvirtProvidersConfigBuilder.setTableOffset(tableOffset);
+ }
+ boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, path,
+ netvirtProvidersConfigBuilder.build());
+
+ LOG.info("NetvirtProvidersConfigImpl: dataBroker= {}, registration= {}, tableOffset= {}, result= {}",
+ dataBroker, registration, tableOffset, result);
+ }
+
+ @Override
+ public void close() throws Exception {
+ registration.close();
+ executorService.shutdown();
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> asyncDataChangeEvent) {
+ executorService.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ LOG.info("onDataChanged: {}", asyncDataChangeEvent);
+ processConfigCreate(asyncDataChangeEvent);
+ processConfigUpdate(asyncDataChangeEvent);
+ }
+ });
+ }
+
+ private void processConfigCreate(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+ for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : changes.getCreatedData().entrySet()) {
+ if (entry.getValue() instanceof NetvirtProvidersConfig) {
+ NetvirtProvidersConfig netvirtProvidersConfig = (NetvirtProvidersConfig) entry.getValue();
+ applyConfig(netvirtProvidersConfig);
+ }
+ }
+ }
+
+ private void processConfigUpdate(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+ for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : changes.getUpdatedData().entrySet()) {
+ if (entry.getValue() instanceof NetvirtProvidersConfig) {
+ LOG.info("processConfigUpdate: {}", entry);
+ NetvirtProvidersConfig netvirtProvidersConfig = (NetvirtProvidersConfig) entry.getValue();
+ applyConfig(netvirtProvidersConfig);
+ }
+ }
+ }
+
+ private void applyConfig(NetvirtProvidersConfig netvirtProvidersConfig) {
+ LOG.info("processConfigUpdate: {}", netvirtProvidersConfig);
+ if (netvirtProvidersConfig.getTableOffset() != null) {
+ NetvirtProvidersProvider.setTableOffset(netvirtProvidersConfig.getTableOffset());
+ }
+ }
+
+ @Override
+ public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
+
+ }
+
+ @Override
+ public void setDependencies(Object impl) {
+
+ }
+}
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static EntityOwnershipService entityOwnershipService;
private ProviderEntityListener providerEntityListener = null;
private static AtomicBoolean hasProviderEntityOwnership = new AtomicBoolean(false);
+ private static short tableOffset;
+ private NetvirtProvidersConfigImpl netvirtProvidersConfig = null;
- public NetvirtProvidersProvider(BundleContext bundleContext, EntityOwnershipService eos) {
+ public NetvirtProvidersProvider(BundleContext bundleContext, EntityOwnershipService eos, short tableOffset) {
LOG.info("NetvirtProvidersProvider: bundleContext: {}", bundleContext);
this.bundleContext = bundleContext;
- entityOwnershipService = eos;
+ entityOwnershipService = eos;
+ setTableOffset(tableOffset);
}
public static DataBroker getDataBroker() {
return hasProviderEntityOwnership.get();
}
+ public static void setTableOffset(short tableOffset) {
+ try {
+ new TableId((short) (tableOffset + Service.L2_FORWARDING.getTable()));
+ } catch (IllegalArgumentException e) {
+ LOG.warn("Invalid table offset: {}", tableOffset, e);
+ return;
+ }
+
+ LOG.info("setTableOffset: changing from {} to {}",
+ NetvirtProvidersProvider.tableOffset, tableOffset);
+ NetvirtProvidersProvider.tableOffset = tableOffset;
+ }
+
+ public static short getTableOffset() {
+ return tableOffset;
+ }
+
@Override
public void close() throws Exception {
LOG.info("NetvirtProvidersProvider closed");
return bridgeName != null && Constants.INTEGRATION_BRIDGE.equals(bridgeName);
}
+ /**
+ * Return the offset adjusted table for this {@link Service}
+ * @return The table id
+ */
public short getTable() {
- return service.getTable();
+ return (short)(orchestrator.getTableOffset() + service.getTable());
+ }
+
+ /**
+ * Return the offset adjusted table for the given {@link Service}
+ * @param service Identifies the openflow {@link Service}
+ * @return The table id
+ */
+ public short getTable(Service service) {
+ return (short)(orchestrator.getTableOffset() + service.getTable());
}
public Service getService() {
protected final InstructionBuilder getMutablePipelineInstructionBuilder() {
Service nextService = orchestrator.getNextServiceInPipeline(service);
if (nextService != null) {
- return InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), nextService.getTable());
+ return InstructionUtils.createGotoTableInstructions(new InstructionBuilder(),
+ orchestrator.getTable(nextService));
} else {
return InstructionUtils.createDropInstructions(new InstructionBuilder());
}
protected void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
if (NetvirtProvidersProvider.isMasterProviderInstance()) {
- LOG.debug("writeFlow 3: flowBuilder: {}, nodeBuilder: {}",
+ LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}",
flowBuilder.build(), nodeBuilder.build());
WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
- LOG.debug("writeFlow: about to put nodePath for Flow {}, nodePath: {}",
- flowBuilder.getFlowName(), createNodePath(nodeBuilder));
modification.put(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder),
nodeBuilder.build(), true /*createMissingParents*/);
- LOG.debug("writeFlow: about to put Flow {}", flowBuilder.getFlowName());
modification.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder),
flowBuilder.build(), true /*createMissingParents*/);
- LOG.debug("writeFlow: about to submit Flow {}", flowBuilder.getFlowName());
CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
- LOG.debug("writeFlow: checking status of Flow {}", flowBuilder.getFlowName());
try {
commitFuture.checkedGet(); // TODO: Make it async (See bug 1362)
LOG.debug("Transaction success for write of Flow {}", flowBuilder.getFlowName());
// Add InstructionsBuilder to FlowBuilder
flowBuilder.setInstructions(isb.build());
- String flowId = "DEFAULT_PIPELINE_FLOW_"+service.getTable();
+ String flowId = "DEFAULT_PIPELINE_FLOW_" + getTable();
flowBuilder.setId(new FlowId(flowId));
FlowKey key = new FlowKey(new FlowId(flowId));
flowBuilder.setMatch(matchBuilder.build());
flowBuilder.setPriority(0);
flowBuilder.setBarrier(false);
- flowBuilder.setTableId(service.getTable());
+ flowBuilder.setTableId(getTable());
flowBuilder.setKey(key);
flowBuilder.setFlowName(flowId);
flowBuilder.setHardTimeout(0);
writeLLDPRule(dpid);
+ if (bridgeName.equals(configurationService.getIntegrationBridgeName()) &&
+ NetvirtProvidersProvider.getTableOffset() != 0) {
+ classifierProvider.programGotoTable(dpid,true);
+ }
+
if (bridgeName.equals(configurationService.getExternalBridgeName())) {
writeNormalRule(dpid);
}
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "NORMAL";
- FlowUtils.initFlowBuilder(flowBuilder, flowName, (short)0).setPriority(0);
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable()).setPriority(0);
MatchBuilder matchBuilder = new MatchBuilder();
flowBuilder.setMatch(matchBuilder.build());
Service getNextServiceInPipeline(Service service);
AbstractServiceInstance getServiceInstance(Service service);
Map<Service, AbstractServiceInstance> getServiceRegistry();
+ short getTableOffset();
+ short getTable(Service service);
List<Service> getStaticPipeline();
void enqueue(Node node);
void registerService(final ServiceReference ref, AbstractServiceInstance serviceInstance);
import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.osgi.framework.BundleContext;
public class PipelineOrchestratorImpl implements ConfigInterface, NodeCacheListener, PipelineOrchestrator {
private static final Logger LOG = LoggerFactory.getLogger(PipelineOrchestratorImpl.class);
+ /**
+ * Return the current table offset
+ * @return The table offset
+ */
+ @Override
+ public short getTableOffset() {
+ return NetvirtProvidersProvider.getTableOffset();
+ }
+
+ /**
+ * Return the offset adjusted table for the given {@link Service}
+ * @param service Identifies the openflow {@link Service}
+ * @return The table id
+ */
+ @Override
+ public short getTable(Service service) {
+ return (short)(getTableOffset() + service.getTable());
+ }
+
public List<Service> getStaticPipeline() {
return staticPipeline;
}
while (true) {
Node node = queue.take();
LOG.info(">>>>> dequeue: {}", node);
- for (Service service : staticPipeline) {
- AbstractServiceInstance serviceInstance = getServiceInstance(service);
- if (serviceInstance != null && southbound.getBridge(node) != null) {
- serviceInstance.programDefaultPipelineRule(node);
+ if (southbound.getBridge(node) != null) {
+ for (Service service : staticPipeline) {
+ AbstractServiceInstance serviceInstance = getServiceInstance(service);
+ if (serviceInstance != null) {
+ serviceInstance.programDefaultPipelineRule(node);
+ }
}
+ // TODO: might need a flow to go from table 0 to the pipeline
}
}
} catch (Exception e) {
@Override
public Status programStaticArpEntry(Long dpid, String segmentationId, String macAddressStr,
InetAddress ipAddress, Action action) {
+ if (ipAddress instanceof Inet6Address) {
+ // WORKAROUND: For now ipv6 is not supported
+ // TODO: implement ipv6 case
+ LOG.debug("ipv6 address case is not implemented yet. dpid {} segmentationId {} macAddressStr, "
+ + "ipAddress {} action {}",
+ dpid, segmentationId, macAddressStr, ipAddress, action);
+ return new Status(StatusCode.NOTIMPLEMENTED);
+ }
+
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "ArpResponder_" + segmentationId + "_" + ipAddress.getHostAddress();
}
}
- if (ipAddress instanceof Inet6Address) {
- // WORKAROUND: For now ipv6 is not supported
- // TODO: implement ipv6 case
- LOG.debug("ipv6 address case is not implemented yet. dpid {} segmentationId {} macAddressStr, "
- + "ipAddress {} action {}",
- dpid, segmentationId, macAddressStr, ipAddress, action);
- return new Status(StatusCode.NOTIMPLEMENTED);
- }
-
flowBuilder.setMatch(matchBuilder.build());
if (action.equals(Action.ADD)) {
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "LLDP";
- FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable());
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(0x88CCL));
writeFlow(flowBuilder, nodeBuilder);
}
+ @Override
+ public void programGotoTable(Long dpidLong, boolean write) {
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ String flowName = "TableOffset_" + getTable();
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable())
+ .setPriority(0);
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+
+ if (write) {
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib =
+ InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), getTable());
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ isb.setInstruction(instructions);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
@Override
public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
super.setDependencies(bundleContext.getServiceReference(ClassifierProvider.class.getName()), this);
@Override
public Status programIpRewriteExclusion(Long dpid, String segmentationId, String excludedCidr,
Action action) {
- NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
- FlowBuilder flowBuilder = new FlowBuilder();
- String flowName = "InboundNATExclusion_" + segmentationId + "_" + excludedCidr;
- FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024);
-
- MatchBuilder matchBuilder = new MatchBuilder();
- MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
String ipAddress = excludedCidr.substring(0, excludedCidr.indexOf("/"));
InetAddress inetAddress;
try {
excludedCidr);
return new Status(StatusCode.NOTIMPLEMENTED);
}
+
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ String flowName = "InboundNATExclusion_" + segmentationId + "_" + excludedCidr;
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024);
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+
MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(excludedCidr));
flowBuilder.setMatch(matchBuilder.build());
@Override
public Status programForwardingTableEntry(Long dpid, String segmentationId, InetAddress ipAddress,
String macAddress, Action action) {
+ if (ipAddress instanceof Inet6Address) {
+ // WORKAROUND: For now ipv6 is not supported
+ // TODO: implement ipv6 case
+ LOG.debug("ipv6 address is not implemented yet. dpid {} segmentationId {} ipAddress {} macAddress {} Action {}",
+ dpid, segmentationId, ipAddress, macAddress, action);
+ return new Status(StatusCode.NOTIMPLEMENTED);
+ }
+
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "L3Forwarding_" + segmentationId + "_" + ipAddress.getHostAddress();
MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
MatchUtils.createDstL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(ipAddress.getHostAddress()));
- if (ipAddress instanceof Inet6Address) {
- // WORKAROUND: For now ipv6 is not supported
- // TODO: implement ipv6 case
- LOG.debug("ipv6 address is not implemented yet. dpid {} segmentationId {} ipAddress {} macAddress {} Action {}",
- dpid, segmentationId, ipAddress, macAddress, action);
- return new Status(StatusCode.NOTIMPLEMENTED);
- }
flowBuilder.setMatch(matchBuilder.build());
if (action.equals(Action.ADD)) {
@Override
public Status programIpRewriteExclusion(Long dpid, String segmentationId, String excludedCidr,
Action action) {
- NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
- FlowBuilder flowBuilder = new FlowBuilder();
- String flowName = "OutboundNATExclusion_" + segmentationId + "_" + excludedCidr;
- FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024);
-
- MatchBuilder matchBuilder = new MatchBuilder();
- MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
-
String ipAddress = excludedCidr.substring(0, excludedCidr.indexOf("/"));
InetAddress inetAddress;
try {
excludedCidr);
return new Status(StatusCode.NOTIMPLEMENTED);
}
+
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ String flowName = "OutboundNATExclusion_" + segmentationId + "_" + excludedCidr;
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024);
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+
MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(excludedCidr));
flowBuilder.setMatch(matchBuilder.build());
@Override
public Status programRouterInterface(Long dpid, String sourceSegId, String destSegId, String macAddress,
InetAddress address, int mask, Action action) {
+ if (address instanceof Inet6Address) {
+ // WORKAROUND: For now ipv6 is not supported
+ // TODO: implement ipv6 case
+ LOG.debug("ipv6 address is not implemented yet. address {}", address);
+ return new Status(StatusCode.NOTIMPLEMENTED);
+ }
SubnetUtils addressSubnetInfo = new SubnetUtils(address.getHostAddress() + "/" + mask);
final String prefixString = addressSubnetInfo.getInfo().getNetworkAddress() + "/" + mask;
MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(sourceSegId));
}
- if (address instanceof Inet6Address) {
- // WORKAROUND: For now ipv6 is not supported
- // TODO: implement ipv6 case
- LOG.debug("ipv6 address is not implemented yet. address {}", address);
- return new Status(StatusCode.NOTIMPLEMENTED);
- }
MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(prefixString));
flowBuilder.setMatch(matchBuilder.build());
private final GatewayMacResolverListener gatewayMacResolverListener;
private final Ipv4Address gatewayIpAddress;
- private final Long externalNetworkBridgeDpid;
+ private Long externalNetworkBridgeDpid;
+ private final boolean refreshExternalNetworkBridgeDpidIfNeeded;
private final Ipv4Address arpRequestSourceIp;
private final MacAddress arpRequestSourceMacAddress;
private final boolean periodicRefresh;
public ArpResolverMetadata(final GatewayMacResolverListener gatewayMacResolverListener,
final Long externalNetworkBridgeDpid,
+ final boolean refreshExternalNetworkBridgeDpidIfNeeded,
final Ipv4Address gatewayIpAddress, final Ipv4Address arpRequestSourceIp,
final MacAddress arpRequestMacAddress, final boolean periodicRefresh){
this.gatewayMacResolverListener = gatewayMacResolverListener;
this.externalNetworkBridgeDpid = externalNetworkBridgeDpid;
+ this.refreshExternalNetworkBridgeDpidIfNeeded = refreshExternalNetworkBridgeDpidIfNeeded;
this.gatewayIpAddress = gatewayIpAddress;
this.arpRequestSourceIp = arpRequestSourceIp;
this.arpRequestSourceMacAddress = arpRequestMacAddress;
this.numberOfOutstandingArpRequests = 0;
}
- public RemoveFlowInput getFlowToRemove() {
- return flowToRemove;
+ public boolean isRefreshExternalNetworkBridgeDpidIfNeeded() {
+ return refreshExternalNetworkBridgeDpidIfNeeded;
}
public boolean isPeriodicRefresh() {
return periodicRefresh;
}
+ public RemoveFlowInput getFlowToRemove() {
+ return flowToRemove;
+ }
public void setFlowToRemove(RemoveFlowInput flowToRemove) {
this.flowToRemove = flowToRemove;
}
public Long getExternalNetworkBridgeDpid() {
return externalNetworkBridgeDpid;
}
+ public void setExternalNetworkBridgeDpid(Long externalNetworkBridgeDpid) {
+ this.externalNetworkBridgeDpid = externalNetworkBridgeDpid;
+ }
public Ipv4Address getArpRequestSourceIp() {
return arpRequestSourceIp;
}
public MacAddress getArpRequestSourceMacAddress() {
return arpRequestSourceMacAddress;
}
+ public boolean isGatewayMacAddressResolved() {
+ return gatewayMacAddressResolved;
+ }
/**
* This method is used to determine whether to use the broadcast MAC or the unicast MAC as the destination address
public int hashCode() {
final int prime = 31;
int result = 1;
+
+ result = prime
+ * result
+ + ((gatewayMacResolverListener == null) ? 0 : gatewayMacResolverListener.hashCode());
result = prime
* result
+ ((arpRequestSourceMacAddress == null) ? 0 : arpRequestSourceMacAddress
* result
+ ((gatewayIpAddress == null) ? 0 : gatewayIpAddress.hashCode());
result = prime * result + (periodicRefresh ? 1231 : 1237);
+ result = prime * result + (refreshExternalNetworkBridgeDpidIfNeeded ? 1231 : 1237);
return result;
}
if (getClass() != obj.getClass())
return false;
ArpResolverMetadata other = (ArpResolverMetadata) obj;
+ if (gatewayMacResolverListener == null) {
+ if (other.gatewayMacResolverListener != null)
+ return false;
+ } else if (!gatewayMacResolverListener.equals(other.gatewayMacResolverListener))
+ return false;
if (arpRequestSourceMacAddress == null) {
if (other.arpRequestSourceMacAddress != null)
return false;
return false;
if (periodicRefresh != other.periodicRefresh)
return false;
+ if (refreshExternalNetworkBridgeDpidIfNeeded != other.refreshExternalNetworkBridgeDpidIfNeeded)
+ return false;
return true;
}
*/
package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.arp;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.math.BigInteger;
-import java.util.Map.Entry;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolver;
import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolverListener;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static com.google.common.base.Preconditions.checkNotNull;
/**
*
implements ConfigInterface, GatewayMacResolver,PacketProcessingListener {
private static final Logger LOG = LoggerFactory.getLogger(GatewayMacResolverService.class);
- private static final short TABLE_FOR_ARP_FLOW = 0;
private static final String ARP_REPLY_TO_CONTROLLER_FLOW_NAME = "GatewayArpReplyRouter";
private static final int ARP_REPLY_TO_CONTROLLER_FLOW_PRIORITY = 10000;
private static final Instruction SEND_TO_CONTROLLER_INSTRUCTION;
private final ScheduledExecutorService gatewayMacRefresherPool = Executors.newScheduledThreadPool(1);
private final ScheduledExecutorService refreshRequester = Executors.newSingleThreadScheduledExecutor();
private AtomicBoolean initializationDone = new AtomicBoolean(false);
+ private volatile ConfigurationService configurationService;
+ private volatile NodeCacheManager nodeCacheManager;
static {
ApplyActions applyActions = new ApplyActionsBuilder().setAction(
if (!gatewayToArpMetadataMap.isEmpty()){
for(final Entry<Ipv4Address, ArpResolverMetadata> gatewayToArpMetadataEntry : gatewayToArpMetadataMap.entrySet()){
final Ipv4Address gatewayIp = gatewayToArpMetadataEntry.getKey();
- final ArpResolverMetadata gatewayMetaData = gatewayToArpMetadataEntry.getValue();
+ final ArpResolverMetadata gatewayMetaData =
+ checkAndGetExternalBridgeDpid(gatewayToArpMetadataEntry.getValue());
gatewayMacRefresherPool.schedule(new Runnable(){
@Override
final Node externalNetworkBridge = getExternalBridge(gatewayMetaData.getExternalNetworkBridgeDpid());
if(externalNetworkBridge == null){
LOG.error("MAC address for gateway {} can not be resolved, because external bridge {} "
- + "is not connected to controller.",gatewayIp.getValue(),gatewayMetaData.getExternalNetworkBridgeDpid() );
+ + "is not connected to controller.",
+ gatewayIp.getValue(),
+ gatewayMetaData.getExternalNetworkBridgeDpid() );
+ } else {
+ LOG.debug("Refresh Gateway Mac for gateway {} using source ip {} and mac {} for ARP request",
+ gatewayIp.getValue(),gatewayMetaData.getArpRequestSourceIp().getValue(),gatewayMetaData.getArpRequestSourceMacAddress().getValue());
+
+ sendGatewayArpRequest(externalNetworkBridge,gatewayIp,gatewayMetaData.getArpRequestSourceIp(), gatewayMetaData.getArpRequestSourceMacAddress());
}
-
- LOG.debug("Refresh Gateway Mac for gateway {} using source ip {} and mac {} for ARP request",
- gatewayIp.getValue(),gatewayMetaData.getArpRequestSourceIp().getValue(),gatewayMetaData.getArpRequestSourceMacAddress().getValue());
-
- sendGatewayArpRequest(externalNetworkBridge,gatewayIp,gatewayMetaData.getArpRequestSourceIp(), gatewayMetaData.getArpRequestSourceMacAddress());
}
}, 1, TimeUnit.SECONDS);
}
* @param sourceIpAddress Source Ip address for the ARP request packet
* @param sourceMacAddress Source Mac address for the ARP request packet
* @param periodicRefresh Enable/Disable periodic refresh of the Gateway Mac address
- * NOTE:Periodic refresh is not supported yet.
* @return Future object
*/
@Override
public ListenableFuture<MacAddress> resolveMacAddress(
final GatewayMacResolverListener gatewayMacResolverListener, final Long externalNetworkBridgeDpid,
+ final Boolean refreshExternalNetworkBridgeDpidIfNeeded,
final Ipv4Address gatewayIp, final Ipv4Address sourceIpAddress, final MacAddress sourceMacAddress,
final Boolean periodicRefresh){
+ Preconditions.checkNotNull(refreshExternalNetworkBridgeDpidIfNeeded);
Preconditions.checkNotNull(sourceIpAddress);
Preconditions.checkNotNull(sourceMacAddress);
Preconditions.checkNotNull(gatewayIp);
}
}else{
gatewayToArpMetadataMap.put(gatewayIp,new ArpResolverMetadata(gatewayMacResolverListener,
- externalNetworkBridgeDpid, gatewayIp,sourceIpAddress,sourceMacAddress,periodicRefresh));
+ externalNetworkBridgeDpid, refreshExternalNetworkBridgeDpidIfNeeded,
+ gatewayIp, sourceIpAddress, sourceMacAddress, periodicRefresh));
}
final Node externalNetworkBridge = getExternalBridge(externalNetworkBridgeDpid);
- if(externalNetworkBridge == null){
- LOG.error("MAC address for gateway {} can not be resolved, because external bridge {} "
- + "is not connected to controller.",gatewayIp.getValue(),externalNetworkBridgeDpid );
+ if (externalNetworkBridge == null) {
+ if (!refreshExternalNetworkBridgeDpidIfNeeded) {
+ LOG.error("MAC address for gateway {} can not be resolved, because external bridge {} "
+ + "is not connected to controller.", gatewayIp.getValue(), externalNetworkBridgeDpid);
+ } else {
+ LOG.debug("MAC address for gateway {} can not be resolved, since dpid was not refreshed yet",
+ gatewayIp.getValue());
+ }
return null;
}
}
private Node getExternalBridge(final Long externalNetworkBridgeDpid){
- final String nodeName = OPENFLOW + externalNetworkBridgeDpid;
+ if (externalNetworkBridgeDpid != null) {
+ final String nodeName = OPENFLOW + externalNetworkBridgeDpid;
+ return getOpenFlowNode(nodeName);
+ }
+ return null;
+ }
+
+ private ArpResolverMetadata checkAndGetExternalBridgeDpid(ArpResolverMetadata gatewayMetaData) {
+ final Long origDpid = gatewayMetaData.getExternalNetworkBridgeDpid();
- return getOpenFlowNode(nodeName);
+ // If we are not allowing dpid to change, there is nothing further to do here
+ if (!gatewayMetaData.isRefreshExternalNetworkBridgeDpidIfNeeded()) {
+ return gatewayMetaData;
+ }
+
+ // If current dpid is null, or if mac is not getting resolved, make an attempt to
+ // grab a different dpid, so a different (or updated) external bridge gets used
+ if (origDpid == null || !gatewayMetaData.isGatewayMacAddressResolved()) {
+ Long newDpid = getAnotherExternalBridgeDpid(origDpid);
+ gatewayMetaData.setExternalNetworkBridgeDpid(newDpid);
+ }
+
+ return gatewayMetaData;
+ }
+
+ private Long getAnotherExternalBridgeDpid(final Long unwantedDpid) {
+ LOG.trace("Being asked to find a new dpid. unwantedDpid:{} cachemanager:{} configurationService:{}",
+ unwantedDpid, nodeCacheManager, configurationService);
+
+ if (nodeCacheManager == null) {
+ LOG.error("Unable to find external dpid to use for resolver: no nodeCacheManager");
+ return unwantedDpid;
+ }
+ if (configurationService == null) {
+ LOG.error("Unable to find external dpid to use for resolver: no configurationService");
+ return unwantedDpid;
+ }
+
+ // Pickup another dpid in list that is different than the unwanted one provided and is in the
+ // operational tree. If none can be found, return the provided dpid as a last resort.
+ // NOTE: We are assuming that all the br-ex are serving one external network and gateway ip of
+ // the external network is reachable from every br-ex
+ // TODO: Consider other deployment scenario, and think of another solution.
+ List<Long> dpids = nodeCacheManager.getBridgeDpids(configurationService.getExternalBridgeName());
+ Collections.shuffle(dpids);
+ for (Long dpid : dpids) {
+ if (dpid == null || dpid.equals(unwantedDpid) || getExternalBridge(dpid) == null) {
+ continue;
+ }
+
+ LOG.debug("Gateway Mac Resolver Service will use dpid {}", dpid);
+ return dpid;
+ }
+
+ LOG.warn("Unable to find usable external dpid for resolver. Best choice is still {}", unwantedDpid);
+ return unwantedDpid;
}
private void sendGatewayArpRequest(final Node externalNetworkBridge,final Ipv4Address gatewayIp,
private Flow createArpReplyToControllerFlow(final ArpMessageAddress senderAddress, final Ipv4Address ipForRequestedMac) {
checkNotNull(senderAddress);
checkNotNull(ipForRequestedMac);
- FlowBuilder arpFlow = new FlowBuilder().setTableId(TABLE_FOR_ARP_FLOW)
+ FlowBuilder arpFlow = new FlowBuilder().setTableId(Service.CLASSIFIER.getTable())
.setFlowName(ARP_REPLY_TO_CONTROLLER_FLOW_NAME)
.setPriority(ARP_REPLY_TO_CONTROLLER_FLOW_PRIORITY)
.setBufferId(OFConstants.OFP_NO_BUFFER)
}
@Override
- public void setDependencies(Object impl) {}
+ public void setDependencies(Object impl) {
+ if (impl instanceof NodeCacheManager) {
+ nodeCacheManager = (NodeCacheManager) impl;
+ } else if (impl instanceof ConfigurationService) {
+ configurationService = (ConfigurationService) impl;
+ }
+ }
@Override
public void stopPeriodicRefresh(Ipv4Address gatewayIp) {
@Override
public java.lang.AutoCloseable createInstance() {
- NetvirtProvidersProvider provider = new NetvirtProvidersProvider(bundleContext, getClusteringEntityOwnershipServiceDependency());
+ NetvirtProvidersProvider provider = new NetvirtProvidersProvider(bundleContext,
+ getClusteringEntityOwnershipServiceDependency(), getTableOffset());
BindingAwareBroker localBroker = getBrokerDependency();
localBroker.registerProvider(provider);
return provider;
--- /dev/null
+module netvirt-providers-config {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:netvirt:providers:config";
+ prefix "netvirt-providers-config";
+
+ revision "2016-01-09" {
+ description "Initial revision of the netvirt providers config";
+ }
+
+ container netvirt-providers-config {
+ description "Configuration for NetvirtProviders";
+
+ config true;
+
+ leaf table-offset {
+ description "The table-offset is used to set the starting table for the netvirt pipeline";
+ type uint8;
+ }
+ }
+}
}
}
}
+
container clustering-entity-ownership-service {
uses config:service-ref {
refine type {
}
}
}
+
+ leaf table-offset {
+ description "The table-offset is used to set the starting table for the netvirt pipeline";
+ type uint8;
+ }
}
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, 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.ovsdb.openstack.netvirt.providers;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestratorImpl;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Unit tests for {@link NetvirtProvidersProvider}
+ */
+public class NetvirtProvidersProviderTest {
+
+ /**
+ * Test for {@link NetvirtProvidersProvider#getTableOffset()}
+ */
+ @Test
+ public void testGetTableOffset() {
+ short tableOffset = 10;
+ NetvirtProvidersProvider netvirtProvidersProvider = new NetvirtProvidersProvider(null, null, tableOffset);
+ assertEquals("Table offset was not set", tableOffset, NetvirtProvidersProvider.getTableOffset());
+ }
+
+ /**
+ * Test for method {@link NetvirtProvidersProvider#setTableOffset(short)}
+ */
+ @Test
+ public void testSetTableOffset() {
+ // verify a good value can be set
+ short tableOffset = 0;
+ NetvirtProvidersProvider netvirtProvidersProvider = new NetvirtProvidersProvider(null, null, tableOffset);
+
+ tableOffset = 10;
+ NetvirtProvidersProvider.setTableOffset(tableOffset);
+ assertEquals("tableOffset was not set", tableOffset, NetvirtProvidersProvider.getTableOffset());
+ }
+
+ /**
+ * Negative test for method {@link NetvirtProvidersProvider#setTableOffset(short)}
+ */
+ @Test
+ public void testTableOffsetNegative() {
+ // verify an out of range value is not set
+ short tableOffset = 0;
+ NetvirtProvidersProvider netvirtProvidersProvider = new NetvirtProvidersProvider(null, null, tableOffset);
+
+ short tableOffsetBad = (short)(256 - Service.L2_FORWARDING.getTable());
+ NetvirtProvidersProvider.setTableOffset(tableOffsetBad);
+ assertEquals("tableOffset should not be set", 0, NetvirtProvidersProvider.getTableOffset());
+ }
+}
private final String NODE_ID = Constants.INTEGRATION_BRIDGE + ":" + ID;
/**
- * Test method {@link AbstractServiceInstance#isBridgeInPipeline(String)}
+ * Test method {@link AbstractServiceInstance#isBridgeInPipeline(Node)}
*/
@Test
public void testIsBridgeInPipeline() {
@Test
public void testGetTable() {
abstractServiceInstance.setService(service);
- assertEquals("Error, getTable() did not return the correct value", 70, abstractServiceInstance.getTable());
+ assertEquals("Error, getTable() did not return the correct value",
+ service.getTable(), abstractServiceInstance.getTable());
+
+ when(orchestrator.getTableOffset()).thenReturn(Service.DIRECTOR.getTable());
+ assertEquals("Error, getTable() did not return the correct value",
+ (short)(Service.DIRECTOR.getTable() + service.getTable()), abstractServiceInstance.getTable());
+ }
+
+ /**
+ * Test method {@link AbstractServiceInstance@getTable(Service}
+ */
+ @Test
+ public void testGetTableWithService() {
+ when(orchestrator.getTableOffset()).thenReturn((short)0);
+ abstractServiceInstance.setService(service);
+ assertEquals("Error, getTables(service) did not return the correct value",
+ Service.L2_FORWARDING.getTable(), abstractServiceInstance.getTable(Service.L2_FORWARDING));
}
@Test
}
/**
- * Test method {@link AbstractServiceInstance#programDefaultPipelineRule(String)}
+ * Test method {@link AbstractServiceInstance#programDefaultPipelineRule(Node)}
*/
@Test
public void testProgramDefaultPipelineRule() {
@Mock private ExecutorService eventHandler;
@Mock private Southbound southbound;
+ /**
+ * Test for method {@link PipelineOrchestratorImpl#getTableOffset()}
+ */
+ @Test
+ public void testGetTableOffset() {
+ short tableOffset = 0;
+ assertEquals("tableOffset was not set", tableOffset, orchestrator.getTableOffset());
+ }
+
+ /**
+ * Test for {@link PipelineOrchestratorImpl#getTable(Service)}
+ */
+ @Test
+ public void testGetTableOffsetWithService() {
+ assertEquals("tableOffset was not set", Service.CLASSIFIER.getTable(),
+ orchestrator.getTable(Service.CLASSIFIER));
+ }
+
/***
* Registers a mock service and verifies the registration by asking the
* pipeline orchestrator to return the associated service from its internal
/**
* Test method
- * {@link PipelineOrchestratorImplr#getNextServiceInPipeline(Service)}
+ * {@link PipelineOrchestratorImpl#getNextServiceInPipeline(Service)}
*/
@Test
public void testGetNextServiceInPipeline() {
sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, true);
sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplName, true);
sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpAddr, true);
+ } else {
+ LOG.info("handleSf: sf and bridge are not on the same node: {} - {}, do nothing",
+ bridgeNode.getNodeId(), serviceFunction.getName());
}
}
String localIp = "";
Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
Node ovsdbNode = southbound.readOvsdbNode(bridgeNode);
+ if (ovsdbNode != null) {
+ localIp = getLocalip(ovsdbNode);
+ }
+ return localIp.equals(String.valueOf(ip.getIp().getValue()));
+ }
+
+ private String getLocalip(Node ovsdbNode) {
+ Preconditions.checkNotNull("The ovsdbNode was null", ovsdbNode);
+ String localIp = null;
if (ovsdbNode != null) {
OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
if (ovsdbNodeAugmentation != null && ovsdbNodeAugmentation.getOpenvswitchOtherConfigs() != null) {
localIp = southbound.getOtherConfig(ovsdbNode, OvsdbTables.OPENVSWITCH, TUNNEL_ENDPOINT_KEY);
}
-
}
- return localIp.equals(String.valueOf(ip.getIp().getValue()));
+ if (localIp == null) {
+ LOG.warn("local_ip was not found for node: {}", ovsdbNode);
+ localIp = "";
+ }
+ return localIp;
}
private boolean isSfOnBridge(Node bridgeNode, ServiceFunction serviceFunction) {
port = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
if (port != null) {
ofPort = southbound.getOFPort(port);
+ LOG.info("found ofPort {} - {}, try: {}", portName, ofPort, i);
break;
}
}
public class SfcClassifierService extends AbstractServiceInstance implements ConfigInterface, ISfcClassifierService {
private static final Logger LOG = LoggerFactory.getLogger(SfcClassifierService.class);
- private static final short TABLE_0 = 0;
private static final short UDP_SHORT = 17;
static int cookieIndex = 0;
flowBuilder.setId(new FlowId(flowId));
FlowKey key = new FlowKey(new FlowId(flowId));
flowBuilder.setBarrier(true);
- flowBuilder.setTableId(TABLE_0);
+ flowBuilder.setTableId(getTable(Service.CLASSIFIER));
flowBuilder.setKey(key);
flowBuilder.setFlowName(flowId);
flowBuilder.setHardTimeout(0);
flowBuilder.setId(new FlowId(flowId));
FlowKey key = new FlowKey(new FlowId(flowId));
flowBuilder.setBarrier(true);
- flowBuilder.setTableId(TABLE_0);
+ flowBuilder.setTableId(getTable(Service.CLASSIFIER));
flowBuilder.setKey(key);
flowBuilder.setFlowName(flowId);
flowBuilder.setHardTimeout(0);
flowBuilder.setId(new FlowId(flowId));
FlowKey key = new FlowKey(new FlowId(flowId));
flowBuilder.setBarrier(true);
- flowBuilder.setTableId(TABLE_0);
+ flowBuilder.setTableId(getTable(Service.CLASSIFIER));
flowBuilder.setKey(key);
flowBuilder.setFlowName(flowId);
flowBuilder.setHardTimeout(0);
ab.setKey(new ActionKey(actionList.size()));
actionList.add(ab.build());
- ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, TABLE_0));
+ ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, Service.CLASSIFIER.getTable()));
ab.setOrder(actionList.size());
ab.setKey(new ActionKey(actionList.size()));
actionList.add(ab.build());
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "sfcEgressClassBypass_" + nsp + "_" + + nsi + "_" + sfOfPort;
- initFlowBuilder(flowBuilder, flowName, TABLE_0, FlowID.FLOW_EGRESSCLASSBYPASS).setPriority(40000);
+ initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(),
+ FlowID.FLOW_EGRESSCLASSBYPASS).setPriority(40000);
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createInPortMatch(matchBuilder, dataPathId, sfOfPort);
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "sfIngress_" + dstPort + "_" + ipAddress;
- initFlowBuilder(flowBuilder, flowName, TABLE_0, FlowID.FLOW_SFINGRESS);
+ initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), FlowID.FLOW_SFINGRESS);
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT);
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "ArpResponder_" + ipAddress;
- initFlowBuilder(flowBuilder, flowName, TABLE_0, FlowID.FLOW_SFARP).setPriority(1024);
+ initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), FlowID.FLOW_SFARP).setPriority(1024);
MacAddress macAddress = new MacAddress(macAddressStr);
package org.opendaylight.ovsdb.openstack.netvirt.sfc;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
import java.io.IOException;
-import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.SfcClassifier;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.AclUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
import org.opendaylight.ovsdb.southbound.SouthboundConstants;
-import org.opendaylight.ovsdb.southbound.SouthboundUtil;
import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
-import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntriesBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.AceBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.ActionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.MatchesBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.ClassifiersBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.Sfc;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.SfcBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
private static String addressStr;
private static String portStr;
private static String connectionType;
+ private static String controllerStr;
private static boolean ovsdb_wait = false;
+ private static String userSpaceEnabled = "no";
+ private static PipelineOrchestrator pipelineOrchestrator;
private static Southbound southbound;
private static DataBroker dataBroker;
public static final String CONTROLLER_IPADDRESS = "ovsdb.controller.address";
public static final String CONNECTION_TYPE_ACTIVE = "active";
public static final String CONNECTION_TYPE_PASSIVE = "passive";
public static final String DEFAULT_SERVER_PORT = "6640";
+ public static final String USERSPACE_ENABLED = "ovsdb.userspace.enabled";
public static final String INTEGRATION_BRIDGE_NAME = "br-int";
private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
private static final String OVSDB_TRACE = "ovsdb.trace";
private static final String SFCPATH = "SFC-Path";
private static final String SFCSF1NAME = "firewall-abstract";
private static final SftType SFCSF1TYPE = new SftType("firewall");
- private static final int GPEPORT = 6633;
+ private static final int GPEUDPPORT = 6633;
@Override
public String getModuleName() {
public Option[] getPropertiesOptions() {
return new Option[] {
propagateSystemProperties(SERVER_IPADDRESS, SERVER_PORT, CONNECTION_TYPE,
- CONTROLLER_IPADDRESS, OVSDB_TRACE, OVSDB_WAIT),
+ CONTROLLER_IPADDRESS, OVSDB_TRACE, OVSDB_WAIT, USERSPACE_ENABLED),
};
}
editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
"log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.sfc",
LogLevel.TRACE.name()),
- //editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
- // "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13",
- // LogLevel.TRACE.name()),
+ editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
+ "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13",
+ LogLevel.TRACE.name()),
editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
"log4j.logger.org.opendaylight.sfc",
LogLevel.TRACE.name()),
addressStr = props.getProperty(SERVER_IPADDRESS);
portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
connectionType = props.getProperty(CONNECTION_TYPE, "active");
- LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
- connectionType, addressStr, portStr);
+ controllerStr = props.getProperty(CONTROLLER_IPADDRESS, "0.0.0.0");
+ userSpaceEnabled = props.getProperty(USERSPACE_ENABLED, "no");
+ LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}, controller ip: {}, " +
+ "userspace.enabled: {}",
+ connectionType, addressStr, portStr, controllerStr, userSpaceEnabled);
if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
if (addressStr == null) {
fail(usage());
}
LOG.info("getProperties {}: {}", OVSDB_TRACE, props.getProperty(OVSDB_TRACE));
LOG.info("getProperties {}: {}", OVSDB_WAIT, props.getProperty(OVSDB_WAIT));
- if (props.getProperty(OVSDB_WAIT).equals("true")) {
+ if (props.getProperty(OVSDB_WAIT) != null && props.getProperty(OVSDB_WAIT).equals("true")) {
ovsdb_wait = true;
}
}
assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, getNetvirtTopology());
southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
assertNotNull("southbound should not be null", southbound);
+ pipelineOrchestrator =
+ (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this);
+ assertNotNull("pipelineOrchestrator should not be null", pipelineOrchestrator);
setup.set(true);
}
testModelDelete(builder, clazz);
}
+ private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz)
+ throws InterruptedException {
+ testModelPut(builder, clazz);
+ Thread.sleep(1000);
+ testModelDelete(builder, clazz);
+ }
+
private ServiceFunctionsBuilder serviceFunctionsBuilder() {
String sf1Name = SF1NAME;
String sf1Ip = SF1IP;
String sf2DplName = SF2DPLNAME;
String sn2Name = SN2NAME;
String bridge2Name= BRIDGE2NAME;
- int port = GPEPORT;
+ int port = GPEUDPPORT;
ServiceFunctionBuilder serviceFunctionBuilder =
serviceFunctionUtils.serviceFunctionBuilder(sf1Ip, port, sf1DplName, sff1Name, sf1Name);
String sn2Name = SN2NAME;
String bridge2Name= BRIDGE2NAME;
String aclName = ACLNAME;
- int port = GPEPORT;
+ int port = GPEUDPPORT;
ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder =
serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder(
@Test
public void testSfcModel() throws InterruptedException {
- testModel(serviceFunctionsBuilder(), ServiceFunctions.class, 3000);
- testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class, 3000);
- testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class, 3000);
- testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class, 3000);
+ int timeout = 1000;
+ testModel(serviceFunctionsBuilder(), ServiceFunctions.class, timeout);
+ testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class, timeout);
+ testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class, timeout);
+ testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class, timeout);
}
@Test
public void testSfcModels() throws InterruptedException {
+ testModel(serviceFunctionsBuilder(), ServiceFunctions.class);
+ testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class);
+ testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class);
+ testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class);
+
+ testModel(accessListsBuilder(), AccessLists.class);
+ testModel(classifiersBuilder(), Classifiers.class);
+ }
+
+ /**
+ * Test that the NetvirtSfc SfcClassifierService is added to the Netvirt pipeline.
+ * @throws InterruptedException
+ */
+ @Test
+ public void testNetvirtSfcPipeline() throws InterruptedException {
String bridgeName = INTEGRATION_BRIDGE_NAME;
- ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
+ ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
+ assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
+ Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
+ assertNotNull("node is not connected", ovsdbNode);
+
+ assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo)
+ + " is not connected", isControllerConnected(connectionInfo));
+
+ Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
+ assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
+ long datapathId = southbound.getDataPathId(bridgeNode);
+ String datapathIdString = southbound.getDatapathId(bridgeNode);
+ LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
+ assertNotEquals("datapathId was not found", datapathId, 0);
+
+ String flowId = "DEFAULT_PIPELINE_FLOW_" + Service.SFC_CLASSIFIER.getTable();
+ verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
+
+ assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
+ Thread.sleep(1000);
+ assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
+ }
+
+ /**
+ * Test the full NetvirtSfc functionality by creating everything needed to realize a chain and
+ * then verify all flows have been created.
+ * NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably.
+ * @throws InterruptedException
+ */
+ @Test
+ public void testNetvirtSfcAll() throws InterruptedException {
+ if (userSpaceEnabled.equals("yes")) {
+ LOG.info("testNetvirtSfcAll: skipping test because userSpaceEnabled {}", userSpaceEnabled);
+ return;
+ }
+ String bridgeName = INTEGRATION_BRIDGE_NAME;
+ ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
assertNotNull("node is not connected", ovsdbNode);
- Thread.sleep(5000);
+ assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo)
+ + " is not connected", isControllerConnected(connectionInfo));
+
Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
long datapathId = southbound.getDataPathId(bridgeNode);
+ String datapathIdString = southbound.getDatapathId(bridgeNode);
+ LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
+ assertNotEquals("datapathId was not found", datapathId, 0);
+
+ String flowId = "DEFAULT_PIPELINE_FLOW_" + Service.SFC_CLASSIFIER.getTable();
+ verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
Map<String, String> externalIds = Maps.newHashMap();
externalIds.put("attached-mac", "f6:00:00:0f:00:01");
southboundUtils.addTerminationPoint(bridgeNode, "vm2", "internal");
Map<String, String> options = Maps.newHashMap();
options.put("key", "flow");
+ options.put("dst_port", String.valueOf(GPEUDPPORT));
+ options.put("remote_ip", "flow");
+ options.put("nshc1", "flow");
+ options.put("nshc2", "flow");
+ options.put("nsp", "flow");
+ options.put("nsi", "flow");
+ southboundUtils.addTerminationPoint(bridgeNode, "vxgpe", "vxlan", options, null);
+ options.clear();
+ options.put("key", "flow");
options.put("remote_ip", "192.168.120.32");
southboundUtils.addTerminationPoint(bridgeNode, "vx", "vxlan", options, null);
- Thread.sleep(1000);
+ long vxGpeOfPort = getOFPort(bridgeNode, "vxgpe");
testModelPut(serviceFunctionsBuilder(), ServiceFunctions.class);
testModelPut(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class);
testModelPut(serviceFunctionChainsBuilder(), ServiceFunctionChains.class);
testModelPut(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class);
- Thread.sleep(5000);
-
testModelPut(accessListsBuilder(), AccessLists.class);
testModelPut(classifiersBuilder(), Classifiers.class);
- Thread.sleep(10000);
-
readwait();
- NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
- FlowBuilder flowBuilder = getSfcIngressClassifierFlowBuilder();
- Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
- assertNotNull("Could not find flow in config", flow);
- flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
- assertNotNull("Could not find flow in operational", flow);
+ flowId = "sfcIngressClass_" + "httpRule";
+ verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
+ flowId = "sfcTable_" + vxGpeOfPort;
+ verifyFlow(datapathId, flowId, Service.CLASSIFIER);
+ flowId = "sfEgress_" + GPEUDPPORT;
+ verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
+ flowId = "sfIngress_" + GPEUDPPORT + "_" + SF1IP;
+ verifyFlow(datapathId, flowId, Service.CLASSIFIER);
+ flowId = "ArpResponder_" + SF1IP;
+ verifyFlow(datapathId, flowId, Service.CLASSIFIER);
assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
Thread.sleep(1000);
assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
}
- /*
- * Connect to an ovsdb node. Netvirt should add br-int, add the controller address
- * and program the pipeline flows.
+ /**
+ * Test the standalone NetvirtSfc implementation
+ * NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably.
+ * @throws InterruptedException
*/
- @Test
- public void testNetvirtSfc() throws InterruptedException {
- String bridgeName = INTEGRATION_BRIDGE_NAME;
- ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
- assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
- Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
- assertNotNull("node is not connected", ovsdbNode);
- ControllerEntry controllerEntry;
- // Loop 10s checking if the controller was added
- for (int i = 0; i < 10; i++) {
- ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
- assertNotNull("ovsdb node not found", ovsdbNode);
- String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
- assertNotNull("Failed to get controller target", controllerTarget);
- OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName);
- if (bridge != null) {
- assertNotNull("Failed to read bridge", bridge);
- assertNotNull("Failed to extract controllerEntry", bridge.getControllerEntry());
- controllerEntry = bridge.getControllerEntry().iterator().next();
- assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
- if (controllerEntry.isIsConnected()) {
- Assert.assertTrue("switch is not connected to the controller", controllerEntry.isIsConnected());
- break;
- }
- }
- Thread.sleep(1000);
- }
-
- Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
- assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
- long datapathId = southbound.getDataPathId(bridgeNode);
-
- //Thread.sleep(10000);
-
- NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
- FlowBuilder flowBuilder = FlowUtils.getPipelineFlow(Service.SFC_CLASSIFIER.getTable(), (short)0);
- Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
- assertNotNull("Could not find flow in config", flow);
- flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
- assertNotNull("Could not find flow in operational", flow);
-
- assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
- Thread.sleep(1000);
- assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
- }
-
@Ignore
@Test
public void testStandalone() throws InterruptedException {
assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
assertNotNull("node is not connected", ovsdbNode);
+
String controllerTarget = "tcp:192.168.50.1:6653";
List<ControllerEntry> setControllerEntry = southboundUtils.createControllerEntry(controllerTarget);
Assert.assertTrue(southboundUtils.addBridge(connectionInfo, null, bridgeName, null, true,
SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
setControllerEntry, null, "00:00:00:00:00:00:00:01"));
- // Loop 10s checking if the controller was added
- for (int i = 0; i < 10; i++) {
- ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
- assertNotNull("ovsdb node not found", ovsdbNode);
- assertNotNull("Failed to get controller target", controllerTarget);
- OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName);
- assertNotNull(bridge);
- assertNotNull(bridge.getControllerEntry());
- ControllerEntry controllerEntry = bridge.getControllerEntry().iterator().next();
- assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
- if (controllerEntry.isIsConnected()) {
- Assert.assertTrue(controllerEntry.isIsConnected());
- break;
- }
- Thread.sleep(1000);
- }
+ assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo)
+ + " is not connected", isControllerConnected(connectionInfo));
Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
long datapathId = southbound.getDataPathId(bridgeNode);
+ String datapathIdString = southbound.getDatapathId(bridgeNode);
+ LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
+ assertNotEquals("datapathId was not found", datapathId, 0);
SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
//sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
sfcClassifier.programSfcClassiferFlows(datapathId, (short)0, "test", matchesBuilder.build(),
nshUtils, (long)2, true);
- nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0);
+ //nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0);
//sfcClassifier.programEgressSfcClassiferFlows(datapathId, (short)0, "test", null,
// nshUtils, (long)2, (long)3, true);
//}
//NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
- //FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1, (short) 0);
+ //FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1,
+ // pipelineOrchestrator.getTable(Service.CLASSIFIER));
//Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
//assertNotNull("Could not find flow in config", flow);
//flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
//assertNotNull("Could not find flow in operational", flow);
- MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build());
- NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
- FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId, (short) 0, "test", null,
- nshUtils, (long) 2, matchBuilder);
- Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
- assertNotNull("Could not find flow in config", flow);
- flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
- assertNotNull("Could not find flow in operational", flow);
+ //MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build());
+ //NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
+ //FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId,
+ // pipelineOrchestrator.getTable(Service.CLASSIFIER), "test", null,
+ // nshUtils, (long) 2, matchBuilder);
+ //Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+ //assertNotNull("Could not find flow in config", flow);
+ //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+ //assertNotNull("Could not find flow in operational", flow);
//nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
- //flowBuilder = getEgressSfcClassifierFlow(datapathId, (short) 0, "test", nshUtils, (long) 2);
+ //flowBuilder = getEgressSfcClassifierFlow(datapathId,
+ //pipelineOrchestrator.getTable(Service.CLASSIFIER),
+ //"test", nshUtils, (long) 2);
//flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
//assertNotNull("Could not find flow in config", flow);
//flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
}
- private FlowBuilder getLocalInPortFlow(long dpidLong, String segmentationId, long inPort, short writeTable) {
- MatchBuilder matchBuilder = new MatchBuilder();
-
- FlowBuilder flowBuilder = new FlowBuilder();
-
- flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
- String flowId = "sfcIngress_" + segmentationId + "_" + inPort;
- flowBuilder.setId(new FlowId(flowId));
- FlowKey key = new FlowKey(new FlowId(flowId));
- flowBuilder.setStrict(true);
- flowBuilder.setBarrier(false);
- flowBuilder.setTableId(writeTable);
- flowBuilder.setKey(key);
- flowBuilder.setFlowName(flowId);
- flowBuilder.setHardTimeout(0);
- flowBuilder.setIdleTimeout(0);
- return flowBuilder;
- }
-
- public FlowBuilder getSfcClassifierFlow(long dpidLong, short writeTable, String ruleName, Matches match,
- NshUtils nshHeader, long tunnelOfPort, MatchBuilder matchBuilder) {
- FlowBuilder flowBuilder = new FlowBuilder();
-
- flowBuilder.setMatch(matchBuilder.build());
-
- String flowId = "sfcClass_" + ruleName + "_" + nshHeader.getNshNsp();
- flowBuilder.setId(new FlowId(flowId));
- FlowKey key = new FlowKey(new FlowId(flowId));
- flowBuilder.setBarrier(true);
- flowBuilder.setTableId(writeTable);
- flowBuilder.setKey(key);
- flowBuilder.setFlowName(flowId);
- flowBuilder.setHardTimeout(0);
- flowBuilder.setIdleTimeout(0);
- return flowBuilder;
- }
-
- private FlowBuilder getEgressSfcClassifierFlow(long dpidLong, short writeTable, String ruleName,
- NshUtils nshHeader, long tunnelOfPort) {
- FlowBuilder flowBuilder = new FlowBuilder();
-
- MatchBuilder matchBuilder = new MatchBuilder();
- flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, tunnelOfPort).build());
- flowBuilder.setMatch(
- MatchUtils.createTunnelIDMatch(matchBuilder, BigInteger.valueOf(nshHeader.getNshNsp())).build());
- flowBuilder.setMatch(MatchUtils.addNxNspMatch(matchBuilder, nshHeader.getNshNsp()).build());
- flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nshHeader.getNshNsi()).build());
-
- String flowId = "egressSfcClass_" + ruleName + "_" + nshHeader.getNshNsp() + "_" + nshHeader.getNshNsi();
- flowBuilder.setId(new FlowId(flowId));
- FlowKey key = new FlowKey(new FlowId(flowId));
- flowBuilder.setStrict(true);
- flowBuilder.setBarrier(false);
- flowBuilder.setTableId(writeTable);
- flowBuilder.setKey(key);
- flowBuilder.setFlowName(flowId);
- flowBuilder.setHardTimeout(0);
- flowBuilder.setIdleTimeout(0);
- return flowBuilder;
- }
-
- private FlowBuilder getSfcIngressClassifierFlowBuilder() {
- FlowBuilder flowBuilder = new FlowBuilder();
- String flowId = "sfcIngressClass_" + "httpRule";
- flowBuilder.setId(new FlowId(flowId));
- FlowKey key = new FlowKey(new FlowId(flowId));
- flowBuilder.setKey(key);
- flowBuilder.setFlowName(flowId);
- flowBuilder.setTableId((short)10);
- return flowBuilder;
- }
-
- private Flow getFlow (FlowBuilder flowBuilder, NodeBuilder nodeBuilder, LogicalDatastoreType store)
- throws InterruptedException {
+ private Flow getFlow (
+ FlowBuilder flowBuilder,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder,
+ LogicalDatastoreType store) throws InterruptedException {
+
Flow flow = null;
for (int i = 0; i < 10; i++) {
+ LOG.info("getFlow try {} from {}: looking for flow: {}, node: {}",
+ i, store, flowBuilder.build(), nodeBuilder.build());
flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
if (flow != null) {
- LOG.info("getFlow: flow: {}: {}", store, flow);
+ LOG.info("getFlow try {} from {}: found flow: {}", i, store, flow);
break;
}
Thread.sleep(1000);
return flow;
}
+ private void verifyFlow(long datapathId, String flowId, Service service) throws InterruptedException {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
+ FlowUtils.createNodeBuilder(datapathId);
+ FlowBuilder flowBuilder =
+ FlowUtils.initFlowBuilder(new FlowBuilder(), flowId, pipelineOrchestrator.getTable(service));
+ Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+ assertNotNull("Could not find flow in config: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
+ flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+ assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
+ }
+
private void readwait() {
if (ovsdb_wait) {
LOG.warn("Waiting, kill with ps -ef | grep java, kill xxx... ");
}
}
}
+
+ private boolean isControllerConnected(ConnectionInfo connectionInfo) throws InterruptedException {
+ LOG.info("isControllerConnected enter");
+ Boolean connected = false;
+ ControllerEntry controllerEntry;
+ Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
+ assertNotNull("ovsdb node not found", ovsdbNode);
+
+ BridgeConfigurationManager bridgeConfigurationManager =
+ (BridgeConfigurationManager) ServiceHelper.getGlobalInstance(BridgeConfigurationManager.class, this);
+ assertNotNull("Could not find BridgeConfigurationManager Service", bridgeConfigurationManager);
+ String controllerTarget = bridgeConfigurationManager.getControllersFromOvsdbNode(ovsdbNode).get(0);
+ Assert.assertNotNull("Failed to get controller target", controllerTarget);
+
+ for (int i = 0; i < 10; i++) {
+ LOG.info("isControllerConnected try {}: looking for controller: {}", i, controllerTarget);
+ OvsdbBridgeAugmentation bridge =
+ southboundUtils.getBridge(connectionInfo, INTEGRATION_BRIDGE_NAME);
+ Assert.assertNotNull(bridge);
+ Assert.assertNotNull(bridge.getControllerEntry());
+ controllerEntry = bridge.getControllerEntry().iterator().next();
+ Assert.assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
+ if (controllerEntry.isIsConnected()) {
+ Assert.assertTrue("Controller is not connected", controllerEntry.isIsConnected());
+ connected = true;
+ break;
+ }
+ Thread.sleep(1000);
+ }
+ LOG.info("isControllerConnected exit: {} - {}", connected, controllerTarget);
+ return connected;
+ }
+
+ private long getOFPort(Node bridgeNode, String portName) {
+ long ofPort = 0L;
+ OvsdbTerminationPointAugmentation port =
+ southbound.extractTerminationPointAugmentation(bridgeNode, portName);
+ if (port != null) {
+ ofPort = southbound.getOFPort(port);
+ }
+ if (ofPort == 0L) {
+ for (int i = 0; i < 10; i++) {
+ LOG.info("Looking for ofPort {}, try: {}", portName, i);
+ TerminationPoint tp = southbound.readTerminationPoint(bridgeNode, null, portName);
+ if (tp != null) {
+ port = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
+ if (port != null) {
+ ofPort = southbound.getOFPort(port);
+ LOG.info("found ofPort {} - {}, try: {}", portName, ofPort, i);
+ break;
+ }
+ }
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ LOG.error("Interrupted while waiting for ofPort {}", portName, e);
+ }
+ }
+ }
+ return ofPort;
+ }
}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev150611.acl.transport.header.fields.DestinationPortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev150611.acl.transport.header.fields.SourcePortRange;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev150611.acl.transport.header.fields.SourcePortRangeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfcBuilder;
public class AclUtils extends AbstractUtils {
public MatchesBuilder matchesBuilder(MatchesBuilder matchesBuilder, int destPort) {
+ SourcePortRangeBuilder sourcePortRangeBuilder = new SourcePortRangeBuilder()
+ .setLowerPort(PortNumber.getDefaultInstance("0"))
+ .setUpperPort(PortNumber.getDefaultInstance("0"));
+
PortNumber portNumber = new PortNumber(destPort);
DestinationPortRangeBuilder destinationPortRangeBuilder = new DestinationPortRangeBuilder()
.setLowerPort(portNumber)
.setUpperPort(portNumber);
AceIpBuilder aceIpBuilder = new AceIpBuilder()
+ .setSourcePortRange(sourcePortRangeBuilder.build())
.setDestinationPortRange(destinationPortRangeBuilder.build())
.setProtocol((short)6)
.setAceIpVersion(new AceIpv4Builder().build());
void programTunnelIn(Long dpidLong, String segmentationId, Long ofPort, boolean write);
void programVlanIn(Long dpidLong, String segmentationId, Long ethPort, boolean write);
void programLLDPPuntRule(Long dpidLong);
+ void programGotoTable(Long dpidLong, boolean write);
}
* periodicRefresh flag.
* @param gatewayMacResolverListener An optional listener for mac update callback (can be null)
* @param externalNetworkBridgeDpid This bridge will be used for sending ARP request
+ * @param refreshExternalNetworkBridgeDpidIfNeeded Instructs resolver to change bridge dpid if resolve is failing
* @param gatewayIp ARP request will be send for this ip address
* @param sourceIpAddress Source IP address for the ARP request (localhost)
* @param sourceMacAddress Source MAC address for the ARP request (localhost)
* @param periodicRefresh Do you want to periodically refresh the gateway mac?
* @return ListenableFuture that contains the mac address of gateway ip.
*/
- public ListenableFuture<MacAddress> resolveMacAddress(final GatewayMacResolverListener gatewayMacResolverListener,
- final Long externalNetworkBridgeDpid, final Ipv4Address gatewayIp, final Ipv4Address sourceIpAddress,
+ public ListenableFuture<MacAddress> resolveMacAddress(
+ final GatewayMacResolverListener gatewayMacResolverListener,
+ final Long externalNetworkBridgeDpid, final Boolean refreshExternalNetworkBridgeDpidIfNeeded,
+ final Ipv4Address gatewayIp, final Ipv4Address sourceIpAddress,
final MacAddress sourceMacAddress, final Boolean periodicRefresh);
/**
List<Node> getNodes();
Map<NodeId, Node> getOvsdbNodes();
List<Node> getBridgeNodes();
+ List<Long> getBridgeDpids(final String bridgeName);
void cacheListenerAdded(final ServiceReference ref, NodeCacheListener handler);
void cacheListenerRemoved(final ServiceReference ref);
package org.opendaylight.ovsdb.openstack.netvirt.impl;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
+import com.google.common.base.Preconditions;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
/**
* Neutron L3 Adapter implements a hub-like adapter for the various Neutron events. Based on
private Boolean enabled = false;
private Boolean flgDistributedARPEnabled = true;
private Boolean isCachePopulationDone = false;
- private final ExecutorService gatewayMacResolverPool = Executors.newFixedThreadPool(5);
private Southbound southbound;
private NeutronModelsDataStoreHelper neutronModelsDataStoreHelper;
LOG.error("Unable to process abstract event " + abstractEvent);
return;
}
+ if (!this.enabled) {
+ return;
+ }
+
NeutronL3AdapterEvent ev = (NeutronL3AdapterEvent) abstractEvent;
switch (ev.getAction()) {
case UPDATE:
public void handleNeutronPortEvent(final NeutronPort neutronPort, Action action) {
LOG.debug("Neutron port {} event : {}", action, neutronPort.toString());
- this.processSecurityGroupUpdate(neutronPort);
if (!this.enabled) {
return;
}
+ this.processSecurityGroupUpdate(neutronPort);
final boolean isDelete = action == Action.DELETE;
if (neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_GATEWAY)){
- if(!isDelete){
- Node externalBridgeNode = getExternalBridgeNode();
- if(externalBridgeNode != null){
- LOG.info("Port {} is network router gateway interface, "
- + "triggering gateway resolution for the attached external network on node {}", neutronPort, externalBridgeNode);
- this.triggerGatewayMacResolver(externalBridgeNode, neutronPort);
- }else{
- LOG.error("Did not find Node that has external bridge (br-ex), Gateway resolution failed");
- }
+ if (!isDelete) {
+ LOG.info("Port {} is network router gateway interface, "
+ + "triggering gateway resolution for the attached external network", neutronPort);
+ this.triggerGatewayMacResolver(neutronPort);
}else{
NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(neutronPort.getNetworkUUID());
*/
try {
NeutronPort originalPort = neutronPort.getOriginalPort();
- if (null == originalPort) {
- LOG.debug("processSecurityGroupUpdate: originalport is empty");
- return;
- }
List<NeutronSecurityGroup> addedGroup = getsecurityGroupChanged(neutronPort,
neutronPort.getOriginalPort());
List<NeutronSecurityGroup> deletedGroup = getsecurityGroupChanged(neutronPort.getOriginalPort(),
private List<NeutronSecurityGroup> getsecurityGroupChanged(NeutronPort port1, NeutronPort port2) {
LOG.trace("getsecurityGroupChanged:" + "Port1:" + port1 + "Port2" + port2);
+ if (port1 == null) {
+ return null;
+ }
List<NeutronSecurityGroup> list1 = new ArrayList<>(port1.getSecurityGroups());
+ if (port2 == null) {
+ return list1;
+ }
List<NeutronSecurityGroup> list2 = new ArrayList<>(port2.getSecurityGroups());
for (Iterator<NeutronSecurityGroup> iterator = list1.iterator(); iterator.hasNext();) {
NeutronSecurityGroup securityGroup1 = iterator.next();
}
private Long getDpidForExternalBridge(Node node) {
- // Check if node is integration bridge; and only then return its dpid
+ // Check if node is external bridge; and only then return its dpid
if (southbound.getBridge(node, configurationService.getExternalBridgeName()) != null) {
return southbound.getDataPathId(node);
}
}
}
- public void triggerGatewayMacResolver(final Node node, final NeutronPort gatewayPort ){
+ private void triggerGatewayMacResolver(final NeutronPort gatewayPort){
- Preconditions.checkNotNull(node);
Preconditions.checkNotNull(gatewayPort);
NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(gatewayPort.getNetworkUUID());
// TODO: address IPv6 case.
if (externalSubnet != null &&
- externalSubnet.getIpVersion() == 4 &&
- gatewayPort.getFixedIPs() != null) {
- LOG.info("Trigger MAC resolution for gateway ip {} on Node {}",externalSubnet.getGatewayIP(),node.getNodeId());
- ListenableFuture<MacAddress> gatewayMacAddress =
- gatewayMacResolver.resolveMacAddress(this,
- getDpidForExternalBridge(node),
- new Ipv4Address(externalSubnet.getGatewayIP()),
- new Ipv4Address(gatewayPort.getFixedIPs().get(0).getIpAddress()),
- new MacAddress(gatewayPort.getMacAddress()),
- true);
- if(gatewayMacAddress != null){
- Futures.addCallback(gatewayMacAddress, new FutureCallback<MacAddress>(){
- @Override
- public void onSuccess(MacAddress result) {
- if(result != null){
- if(!result.getValue().equals(externalRouterMac)){
- updateExternalRouterMac(result.getValue());
- LOG.info("Resolved MAC address for gateway IP {} is {}", externalSubnet.getGatewayIP(),result.getValue());
- }
- }else{
- LOG.warn("MAC address resolution failed for gateway IP {}", externalSubnet.getGatewayIP());
- }
- }
-
- @Override
- public void onFailure(Throwable t) {
- LOG.warn("MAC address resolution failed for gateway IP {}", externalSubnet.getGatewayIP());
- }
- }, gatewayMacResolverPool);
- }
+ externalSubnet.getIpVersion() == 4 &&
+ gatewayPort.getFixedIPs() != null) {
+ LOG.info("Trigger MAC resolution for gateway ip {}", externalSubnet.getGatewayIP());
+
+ gatewayMacResolver.resolveMacAddress(
+ this, /* gatewayMacResolverListener */
+ null, /* externalNetworkBridgeDpid */
+ true, /* refreshExternalNetworkBridgeDpidIfNeeded */
+ new Ipv4Address(externalSubnet.getGatewayIP()),
+ new Ipv4Address(gatewayPort.getFixedIPs().get(0).getIpAddress()),
+ new MacAddress(gatewayPort.getMacAddress()),
+ true /* periodicRefresh */);
} else {
LOG.warn("No gateway IP address found for external network {}", externalNetwork);
}
import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
return nodes;
}
+ @Override
+ public List <Long> getBridgeDpids(final String bridgeName) {
+ List<Long> dpids = Lists.newArrayList();
+ for (Node node : nodeCache.values()) {
+ if (bridgeName == null || southbound.getBridge(node, bridgeName) != null) {
+ long dpid = southbound.getDataPathId(node);
+ if (dpid != 0L) {
+ dpids.add(Long.valueOf(dpid));
+ }
+ }
+ }
+ return dpids;
+ }
+
@Override
public List<Node> getNodes() {
List<Node> nodes = Lists.newArrayList();
}
public String getDatapathId(Node node) {
- String datapathId = null;
OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.getAugmentation(OvsdbBridgeAugmentation.class);
- if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
- datapathId = node.getAugmentation(OvsdbBridgeAugmentation.class).getDatapathId().getValue();
- }
- return datapathId;
+ return getDatapathId(ovsdbBridgeAugmentation);
}
public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
}
try {
- List<OvsdbTerminationPointAugmentation> ports = southbound.getTerminationPointsOfBridge(node);
+ // Make sure to get fresh list of termination points, and not use the ones provided in node param!
+ List<OvsdbTerminationPointAugmentation> ports = southbound.readTerminationPointAugmentations(node);
+
for (OvsdbTerminationPointAugmentation port : ports) {
String ifaceId = southbound.getInterfaceExternalIdsValue(port, Constants.EXTERNAL_ID_INTERFACE_ID);
if (ifaceId != null && isInterfacePresentInTenantNetwork(ifaceId, networkId)) {
assertNotNull("Error, hashCode() did not return any value", abstractEvent1.hashCode());
assertEquals("Error, hashCode() is not consistent", abstractEvent2.hashCode(), abstractEvent3.hashCode());
+ int transactionId = abstractEvent1.getTransactionId();
assertEquals("Error, toString() did not return the correct value",
- "AbstractEvent [transactionId=1 handlerType=SOUTHBOUND action=DELETE]", abstractEvent1.toString());
+ "AbstractEvent [transactionId=" + transactionId + " handlerType=SOUTHBOUND action=DELETE]", abstractEvent1.toString());
}
}
List<OvsdbTerminationPointAugmentation> ports = new ArrayList<>();
ports.add(mock(OvsdbTerminationPointAugmentation.class));
- when(southbound.getTerminationPointsOfBridge(any(Node.class))).thenReturn(ports);
+ when(southbound.readTerminationPointAugmentations(any(Node.class))).thenReturn(ports);
assertTrue("Error, did not return correct boolean for isTenantNetworkPresentInNode", tenantNetworkManagerImpl.isTenantNetworkPresentInNode(mock(Node.class), SEG_ID));
}