--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ /*
+ ~ * Copyright (C) 2014 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
+ ~ *
+ ~ * Authors : Sam Hague
+ ~ */
+ -->
+
+<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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>commons</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ <relativePath>../../commons/parent</relativePath>
+ </parent>
+ <artifactId>features-ovs-sfc</artifactId>
+ <name>OpenDaylight OVSDB OVS Service Function Chaining Karaf Features</name>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <properties>
+ <features.file>features.xml</features.file>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>features-openflow-nxm</artifactId>
+ <version>${openflowplugin.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>features-ovsdb</artifactId>
+ <version>${ovsdb.library.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>features-test</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-empty</artifactId>
+ <type>zip</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>plugin</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>ovssfc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.sfc</groupId>
+ <artifactId>sfc-model</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <resources>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>filter</id>
+ <goals>
+ <goal>resources</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/${features.file}</file>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>${skip.karaf}</skip>
+ <systemPropertyVariables>
+ <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+ <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+ <karaf.distro.version>1.4.2-SNAPSHOT</karaf.distro.version>
+ </systemPropertyVariables>
+ <dependenciesToScan>
+ <dependency>org.opendaylight.yangtools:features-test</dependency>
+ </dependenciesToScan>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/ovsdb.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/ovsdb.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://wiki.opendaylight.org/view/OVSDB_Integration:Main</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ <features name="ovsdb-${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-nsf/${nsf.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.ovsdb/features-openflow-nxm/${openflowplugin.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.ovsdb/features-ovsdb/${ovsdb.library.version}/xml/features</repository>
+
+ <feature name="odl-ovsdb-ovssfc"
+ description="OpenDaylight :: OVSDB :: OVS Service Function Chaining"
+ version='${ovsdb.ovssfc.version}'>
+ <feature version="${ovsdb.plugin.version}">odl-ovsdb-plugin</feature>
+ <feature version="${openflowplugin.version}">odl-openflow-nxm-extensions</feature>
+ <feature version="${nsf.version}">odl-nsf-all</feature>
+ <bundle>mvn:org.opendaylight.sfc/sfc-model/${sfc-model.version}</bundle>
+ <bundle>mvn:org.opendaylight.ovsdb/ovssfc/${ovsdb.ovssfc.version}</bundle>
+ </feature>
+</features>
--- /dev/null
+/*
+ * Copyright (c) 2014 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
+ *
+ * Authors : Madhu Venugopal
+ */
+package org.opendaylight.ovsdb.integrationtest.plugin;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperty;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.inject.Inject;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.ovsdb.integrationtest.ConfigurationBundles;
+import org.opendaylight.ovsdb.integrationtest.OvsdbIntegrationTestBase;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
+import org.opendaylight.ovsdb.lib.notation.Row;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.plugin.api.Connection;
+import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
+import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
+import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryListener;
+import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryService;
+import org.opendaylight.ovsdb.plugin.api.StatusWithUuid;
+import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.util.PathUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+
+@RunWith(PaxExam.class)
+public class OvsdbPluginV3IT extends OvsdbIntegrationTestBase {
+ private Logger log = LoggerFactory.getLogger(OvsdbPluginV3IT.class);
+ @Inject
+ private BundleContext bc;
+ private OvsdbConfigurationService ovsdbConfigurationService = null;
+ private String databaseName = "Open_vSwitch";
+
+ @Inject
+ private OvsdbInventoryService ovsdbInventoryService;
+
+ private Node node = null;
+ private OvsdbClient client = null;
+
+ // Configure the OSGi container
+ @Configuration
+ public Option[] config() {
+ return options(
+ //
+ systemProperty("logback.configurationFile").value(
+ "file:" + PathUtils.getBaseDir()
+ + "/src/test/resources/logback.xml"
+ ),
+ // To start OSGi console for inspection remotely
+ systemProperty("osgi.console").value("2401"),
+
+ propagateSystemProperty("ovsdbserver.ipaddress"),
+ propagateSystemProperty("ovsdbserver.port"),
+
+ ConfigurationBundles.controllerBundles(),
+ ConfigurationBundles.ovsdbLibraryBundles(),
+ ConfigurationBundles.ovsdbDefaultSchemaBundles(),
+ ConfigurationBundles.ovsdbPluginBundles(),
+ junitBundles()
+ );
+ }
+
+ private String stateToString(int state) {
+ switch (state) {
+ case Bundle.ACTIVE:
+ return "ACTIVE";
+ case Bundle.INSTALLED:
+ return "INSTALLED";
+ case Bundle.RESOLVED:
+ return "RESOLVED";
+ case Bundle.UNINSTALLED:
+ return "UNINSTALLED";
+ default:
+ return "Not CONVERTED";
+ }
+ }
+
+ @Before
+ public void areWeReady() throws InterruptedException {
+ assertNotNull(bc);
+ boolean debugit = false;
+ Bundle b[] = bc.getBundles();
+ for (Bundle element : b) {
+ int state = element.getState();
+ if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
+ log.info("Bundle:" + element.getSymbolicName() + " state:"
+ + stateToString(state));
+ debugit = true;
+ }
+ }
+ if (debugit) {
+ log.debug("Do some debugging because some bundle is unresolved");
+ }
+
+ assertFalse(debugit);
+ try {
+ node = getPluginTestConnection();
+ } catch (Exception e) {
+ fail("Exception : "+e.getMessage());
+ }
+ this.ovsdbConfigurationService = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class, this);
+ }
+
+ @Test
+ public void apiTests() throws Exception {
+ Thread.sleep(5000);
+ OvsdbConnectionService
+ connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
+
+ // Check for the ovsdb Connection as seen by the Plugin layer
+ assertNotNull(connectionService.getNodes());
+ assertTrue(connectionService.getNodes().size() > 0);
+ Node node = connectionService.getNodes().get(0);
+ Connection connection = connectionService.getConnection(node);
+ OvsdbConnectionInfo connectionInfo = connection.getClient().getConnectionInfo();
+ String identifier = IDENTIFIER;
+ if (connectionInfo.getType().equals(OvsdbConnectionInfo.ConnectionType.PASSIVE)) {
+ identifier = connectionInfo.getRemoteAddress().getHostAddress()+":"+connectionInfo.getRemotePort();
+ }
+ assertEquals(Node.fromString("OVS|" + identifier), connectionService.getNodes().get(0));
+ System.out.println("Nodes = "+ connectionService.getNodes());
+ /*
+ * Test sequence :
+ * 1. Print Cache and Assert to make sure the bridge is not created yet.
+ * 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
+ * 3. Assert to make sure the bridge is created with a valid Uuid.
+ * 4. Delete the bridge & Assert to make sure the return status is success.
+ * 5. Assert to make sure the bridge is deleted
+ */
+
+ this.endToEndApiTest(connection, getOpenVSwitchTableUUID(connection));
+ }
+
+ @Test
+ public void testInventoryListeners() throws UnknownHostException {
+ DependencyManager dm = new DependencyManager(bc);
+
+ OvsdbInventoryListener listenerA = Mockito.mock(FakeListener.class);
+ OvsdbInventoryListener listenerB = Mockito.mock(FakeListener.class);
+
+ Component componentA = dm.createComponent();
+ componentA.setInterface(OvsdbInventoryListener.class.getName(), null);
+ componentA.setImplementation(listenerA);
+ dm.add(componentA);
+
+ Component componentB = dm.createComponent();
+ componentB.setInterface(OvsdbInventoryListener.class.getName(), null);
+ componentB.setImplementation(listenerB);
+ dm.add(componentB);
+
+ Node newNode = Node.fromString("OVS:10.10.10.10:65342");
+ InetAddress address = InetAddress.getByName("10.10.10.10");
+ int port = 65342;
+
+ // Trigger event
+ ovsdbInventoryService.notifyNodeAdded(newNode, address, port);
+
+ Mockito.verify(listenerA, Mockito.times(1)).nodeAdded(newNode, address, port);
+ Mockito.verify(listenerB, Mockito.times(1)).nodeAdded(newNode, address, port);
+
+ dm.remove(componentA);
+ dm.remove(componentB);
+
+ }
+
+ public void endToEndApiTest(Connection connection, String parentUuid) throws Exception {
+ // 1. Print Cache and Assert to make sure the bridge is not created yet.
+ printCache();
+
+ // 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
+ StatusWithUuid status = insertBridge(connection, parentUuid);
+ assertTrue(status.isSuccess());
+
+ Thread.sleep(2000);
+
+ // 3. Assert to make sure the bridge is created with a valid Uuid.
+ printCache();
+ Bridge bridge = connection.getClient().getTypedRowWrapper(Bridge.class, null);
+ Row bridgeRow = ovsdbConfigurationService.getRow(node, databaseName, bridge.getSchema().getName(), status.getUuid());
+ assertNotNull(bridgeRow);
+ bridge = connection.getClient().getTypedRowWrapper(Bridge.class, bridgeRow);
+ System.out.println("Bridge UUID "+bridge.getUuid()+" Status Uuid "+status.getUuid());
+ assertEquals(bridge.getUuid(), status.getUuid());
+
+ bridge = connection.getClient().createTypedRowWrapper(Bridge.class);
+ bridge.setDatapathType("netdev");
+ try {
+ ovsdbConfigurationService.updateRow(node, databaseName, bridge.getSchema().getName(), status.getUuid(), bridge.getRow(), false);
+ } catch (Exception e) {
+ fail("Failed to updated Bridge "+e.getMessage());
+ }
+
+ // 4. Delete the bridge & Assert to make sure the return status is success.
+ try {
+ ovsdbConfigurationService.deleteRow(node, databaseName, bridge.getSchema().getName(), null, new UUID(parentUuid) ,null, status.getUuid());
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ Thread.sleep(2000);
+
+ // 5. Assert to make sure the bridge is deleted
+ bridgeRow = ovsdbConfigurationService.getRow(node, databaseName, bridge.getSchema().getName(), status.getUuid());
+ assertNull(bridgeRow);
+ }
+
+ public StatusWithUuid insertBridge(Connection connection, String parentUuid) throws Exception {
+ Bridge bridge = connection.getClient().createTypedRowWrapper(Bridge.class);
+ bridge.setName("br_test1");
+ bridge.setStatus(ImmutableMap.of("key", "value"));
+ bridge.setFloodVlans(Sets.newHashSet(34L));
+ try {
+ Row<GenericTableSchema> row = ovsdbConfigurationService.insertTree(node, databaseName, bridge.getSchema().getName(), new UUID(parentUuid), bridge.getRow());
+ bridge = connection.getClient().getTypedRowWrapper(Bridge.class, row);
+ return new StatusWithUuid(StatusCode.SUCCESS, bridge.getUuid());
+ } catch (Exception e) {
+ return new StatusWithUuid(StatusCode.INTERNALERROR);
+ }
+ }
+
+ public String getOpenVSwitchTableUUID(Connection connection) throws Exception {
+ OpenVSwitch openVSwitch = connection.getClient().getTypedRowWrapper(OpenVSwitch.class, null);
+ ConcurrentMap<UUID, Row<GenericTableSchema>> rows = ovsdbConfigurationService.getRows(node, databaseName, openVSwitch.getSchema().getName());
+ if (rows == null || rows.size() == 0) return null;
+ return rows.keySet().toArray()[0].toString();
+ }
+
+ public void printCache() throws Exception {
+ List<String> tables = ovsdbConfigurationService.getTables(node, databaseName);
+ System.out.println("Tables = "+tables);
+ assertNotNull(tables);
+ for (String table : tables) {
+ System.out.println("Table "+table);
+ ConcurrentMap<UUID, Row<GenericTableSchema>> rows = ovsdbConfigurationService.getRows(node, databaseName, table);
+ System.out.println(rows);
+ }
+ }
+
+ public class FakeListener implements OvsdbInventoryListener {
+
+ @Override
+ public void nodeAdded(Node node, InetAddress address, int port) {
+
+ }
+
+ @Override
+ public void nodeRemoved(Node node) {
+
+ }
+
+ @Override
+ public void rowAdded(Node node, String tableName, String uuid, Row row) {
+
+ }
+
+ @Override
+ public void rowUpdated(Node node, String tableName, String uuid, Row old, Row row) {
+
+ }
+
+ @Override
+ public void rowRemoved(Node node, String tableName, String uuid, Row row, Object context) {
+
+ }
+ }
+
+}
package org.opendaylight.ovsdb.northbound;
+import java.util.List;
+
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
/**
* Northbound interface for OVSDB Databases
*/
public class DatabaseResource {
String nodeId;
-
+ ObjectMapper objectMapper;
DatabaseResource(String id) {
this.nodeId = id;
+ objectMapper = new ObjectMapper();
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ }
+
+ private DatabaseSchema getDatabaseSchema (String databaseName) {
+ String csDatabaseName = this.caseSensitiveDatabaseName(databaseName);
+ OvsdbClient client = NodeResource.getOvsdbConnection(nodeId, this);
+ return client.getDatabaseSchema(csDatabaseName);
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getDatabases(){
- return Response.noContent().build();
+ OvsdbClient client = NodeResource.getOvsdbConnection(nodeId, this);
+ try {
+ List<String> databases = client.getDatabases().get();
+ if (databases == null) {
+ return Response.noContent().build();
+ }
+ String response = objectMapper.writeValueAsString(databases);
+ return Response.status(Response.Status.OK)
+ .entity(response)
+ .build();
+ } catch (Exception e) {
+ throw new InternalServerErrorException("Failed due to exception " + e.getMessage());
+ }
}
@GET
@Path("{name}")
@Produces(MediaType.APPLICATION_JSON)
- public Response getDatabases(@PathParam("name") String name){
- return Response.noContent().build();
+ public Response getDatabases(@PathParam("name") String name) throws JsonProcessingException {
+ DatabaseSchema dbSchema = this.getDatabaseSchema(name);
+ String response = objectMapper.writeValueAsString(dbSchema);
+ return Response.status(Response.Status.OK)
+ .entity(response)
+ .build();
}
@Path("{name}/table")
public TableResource getDatabaseTables(@PathParam("name") String name){
- return new TableResource(nodeId, name);
+ String csDatabaseName = this.caseSensitiveDatabaseName(name);
+ return new TableResource(nodeId, csDatabaseName);
}
+ private String caseSensitiveDatabaseName (String ciDatabaseName) {
+ Node node = Node.fromString(nodeId);
+ OvsdbConnectionService connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
+ OvsdbClient client = connectionService.getConnection(node).getClient();
+
+ try {
+ List<String> databases = client.getDatabases().get();
+ if (databases == null) return ciDatabaseName;
+ for (String csDatabaseName : databases) {
+ if (csDatabaseName.equalsIgnoreCase(ciDatabaseName)) return csDatabaseName;
+ }
+ return ciDatabaseName;
+ } catch (Exception e) {
+ return ciDatabaseName;
+ }
+ }
}
package org.opendaylight.ovsdb.northbound;
import java.io.InputStream;
+import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
+import org.opendaylight.ovsdb.plugin.api.Connection;
+import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.Lists;
+
/**
* Northbound Interface for OVSDB Nodes
*/
public class NodeResource {
+ ObjectMapper objectMapper;
+ public NodeResource () {
+ objectMapper = new ObjectMapper();
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ }
+
+ public static OvsdbClient getOvsdbConnection(String nodeId, Object bundleClassRef) {
+ Node node = Node.fromString(nodeId);
+ if (node == null) {
+ throw new ResourceNotFoundException("Node "+nodeId+" not found");
+ }
+ OvsdbConnectionService connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, bundleClassRef);
+ Connection connection = connectionService.getConnection(node);
+ if (connection == null) {
+ throw new ResourceNotFoundException("Connection for "+nodeId+" not available");
+ }
+ OvsdbClient client = connectionService.getConnection(node).getClient();
+ if (client == null) {
+ throw new ResourceNotFoundException("No Ovsdb Client to handle Node "+nodeId);
+ }
+ return client;
+ }
@GET
@Produces(MediaType.APPLICATION_JSON)
- public Response getNodes(){
- return Response.noContent().build();
+ public Response getNodes() throws JsonProcessingException {
+ OvsdbConnectionService connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
+ List<Node> nodes = connectionService.getNodes();
+ if (nodes == null) return Response.noContent().build();
+
+ List<String> nodeIds = Lists.newArrayList();
+ for (Node node : nodes) {
+ nodeIds.add(node.toString());
+ }
+
+ String response = objectMapper.writeValueAsString(nodeIds);
+ return Response.status(Response.Status.OK)
+ .entity(response)
+ .build();
}
@POST
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
- public Response getNode(@PathParam("id") String id){
- return Response.noContent().build();
+ public Response getNode(@PathParam("id") String id) throws JsonProcessingException {
+ OvsdbConnectionService connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
+ OvsdbClient client = NodeResource.getOvsdbConnection(id, this);
+ if (client == null) {
+ throw new ResourceNotFoundException("Node "+id+" not found");
+ }
+ OvsdbConnectionInfo connectionInfo = client.getConnectionInfo();
+ String response = objectMapper.writeValueAsString(connectionInfo);
+ return Response.status(Response.Status.OK)
+ .entity(response)
+ .build();
}
@PUT
import java.util.Iterator;
import java.util.concurrent.ExecutionException;
-import javax.xml.bind.annotation.XmlElement;
-
import org.opendaylight.ovsdb.lib.OvsdbClient;
import org.opendaylight.ovsdb.lib.notation.Row;
import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
-@Deprecated
public class OvsdbRow {
private static final String PARENTUUID = "parent_uuid";
+ private static final String PARENTTABLE = "parent_table";
+ private static final String PARENTCOLUMN = "parent_column";
private static final String ROW = "row";
- @XmlElement(name=PARENTUUID)
- String parentUuid;
-
- String tableName;
-
- @XmlElement(name=ROW)
- Row<GenericTableSchema> row;
+ private String parentUuid;
+ private String parentTable;
+ private String parentColumn;
+ private String tableName;
+ private Row<GenericTableSchema> row;
public OvsdbRow() {
}
this.row = row;
}
+ public OvsdbRow(String parentTable, String parentUuid, String parentColumn, String tableName, Row<GenericTableSchema> row) {
+ this.parentTable = parentTable;
+ this.parentColumn = parentColumn;
+ this.parentUuid = parentUuid;
+ this.tableName = tableName;
+ this.row = row;
+ }
+
public static OvsdbRow fromJsonNode(OvsdbClient client, String dbName, JsonNode json) {
JsonNode parentUuidNode = json.get(PARENTUUID);
String parentUuid = null;
if (parentUuidNode != null) parentUuid = parentUuidNode.asText();
+ JsonNode parentTableNode = json.get(PARENTTABLE);
+ String parentTable = null;
+ if (parentTableNode != null) parentTable = parentTableNode.asText();
+
+ JsonNode parentColumnNode = json.get(PARENTCOLUMN);
+ String parentColumn = null;
+ if (parentColumnNode != null) parentColumn = parentColumnNode.asText();
+
JsonNode rowNode = json.get(ROW);
if (rowNode == null) return null;
for(Iterator<String> fieldNames = rowNode.fieldNames(); fieldNames.hasNext();) {
e.printStackTrace();
return null;
}
- return new OvsdbRow(parentUuid, tableName, row);
+ return new OvsdbRow(parentTable, parentUuid, parentColumn, tableName, row);
}
return null;
}
return schema.createRow((ObjectNode)rowJson);
}
+ public String getParentTable() {
+ return parentTable;
+ }
+
public String getParentUuid() {
return parentUuid;
}
+ public String getParentColumn() {
+ return parentColumn;
+ }
+
public String getTableName() {
return tableName;
}
public Row<GenericTableSchema> getRow() {
return row;
}
-
- @Override
- public String toString() {
- return "OVSDBRow [parentUuid=" + parentUuid + ", tableName="
- + tableName + ", row=" + row + "]";
- }
}
package org.opendaylight.ovsdb.northbound;
+import java.io.BufferedReader;
+import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Map;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.notation.Row;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.plugin.api.OvsVswitchdSchemaConstants;
+import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
/**
* Northbound interface for OVSDB Rows
*/
String nodeId;
String databaseName;
- String rowName;
+ String tableName;
+ ObjectMapper objectMapper;
- public RowResource(String nodeId, String databaseName, String rowName) {
+ public RowResource(String nodeId, String databaseName, String tableName) {
this.nodeId = nodeId;
this.databaseName = databaseName;
- this.rowName = rowName;
+ this.tableName = tableName;
+ objectMapper = new ObjectMapper();
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ }
+
+ private OvsdbRow getOvsdbRow (InputStream stream) throws IOException {
+ StringBuilder rowNodeStrBuilder = new StringBuilder();
+ BufferedReader in = new BufferedReader(new InputStreamReader(stream));
+ String line = null;
+ while ((line = in.readLine()) != null) {
+ rowNodeStrBuilder.append(line);
+ }
+ JsonNode jsonNode = objectMapper.readTree(rowNodeStrBuilder.toString());
+ OvsdbClient client = NodeResource.getOvsdbConnection(nodeId, this);
+ return OvsdbRow.fromJsonNode(client, OvsVswitchdSchemaConstants.DATABASE_NAME, jsonNode);
}
@GET
@Produces(MediaType.APPLICATION_JSON)
- public Response getRows(){
- return Response.noContent().build();
+ public Response getRows() throws JsonProcessingException {
+ OvsdbConfigurationService
+ ovsdbTable = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class,
+ this);
+ if (ovsdbTable == null) {
+ throw new ServiceUnavailableException("Ovsdb ConfigurationService " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Node node = Node.fromString(nodeId);
+ Map<UUID,Row<GenericTableSchema>> rows = null;
+ try {
+ rows = ovsdbTable.getRows(node, databaseName, tableName);
+ } catch (Exception e) {
+ throw new BadRequestException(e.getMessage());
+ }
+ String response = objectMapper.writeValueAsString(rows);
+ return Response.status(Response.Status.OK)
+ .entity(response)
+ .build();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
- public Response createRow(InputStream stream) {
- return Response.noContent().build();
+ public Response createRow(InputStream stream) throws IOException {
+ Node node = Node.fromString(nodeId);
+ OvsdbRow localRow = this.getOvsdbRow(stream);
+ if (localRow == null) {
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ OvsdbConfigurationService
+ ovsdbTable = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class,
+ this);
+ if (ovsdbTable == null) {
+ throw new ServiceUnavailableException("OVS Configuration Service " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Row row = ovsdbTable.insertTree(node, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName,
+ localRow.getParentTable(), new UUID(localRow.getParentUuid()), localRow.getParentColumn(),
+ localRow.getRow());
+ String response = objectMapper.writeValueAsString(row);
+ return Response.status(Response.Status.CREATED)
+ .entity(response)
+ .build();
}
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
- public Response getRowDetails(@PathParam("id") String id){
- return Response.noContent().build();
+ public Response getRowDetails(@PathParam("id") String id) throws JsonProcessingException {
+ OvsdbConfigurationService
+ ovsdbTable = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class,
+ this);
+ if (ovsdbTable == null) {
+ throw new ServiceUnavailableException("Ovsdb ConfigurationService " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Node node = Node.fromString(nodeId);
+ Row<GenericTableSchema> row = null;
+ try {
+ row = ovsdbTable.getRow(node, databaseName, tableName, new UUID(id));
+ } catch (Exception e) {
+ throw new BadRequestException(e.getMessage());
+ }
+ String response = objectMapper.writeValueAsString(row);
+ return Response.status(Response.Status.OK)
+ .entity(response)
+ .build();
}
@PUT
@Path("{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
- public Response updateRow(@PathParam("id") String id){
- return Response.noContent().build();
+ public Response updateRow(@PathParam("id") String id, InputStream stream) throws IOException{
+ Node node = Node.fromString(nodeId);
+ OvsdbRow localRow = this.getOvsdbRow(stream);
+ if (localRow == null) {
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ OvsdbConfigurationService ovsdbTable = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class,
+ this);
+ if (ovsdbTable == null) {
+ throw new ServiceUnavailableException("OVS Configuration Service " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Row<GenericTableSchema> row = ovsdbTable.updateRow(node, databaseName, tableName, new UUID(id), localRow.getRow(), true);
+ String response = objectMapper.writeValueAsString(row);
+ return Response.status(Response.Status.OK)
+ .entity(response)
+ .build();
}
@DELETE
@Path("{id}")
@Consumes(MediaType.APPLICATION_JSON)
public Response deleteRow(@PathParam("id") String id){
- return Response.noContent().build();
- }
+ OvsdbConfigurationService
+ ovsdbTable = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class,
+ this);
+ if (ovsdbTable == null) {
+ throw new ServiceUnavailableException("Ovsdb ConfigurationService " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ Node node = Node.fromString(nodeId);
+ try {
+ ovsdbTable.deleteRow(node, databaseName, tableName, new UUID(id));
+ } catch (Exception e) {
+ throw new BadRequestException(e.getMessage());
+ }
+ return Response.status(Response.Status.OK)
+ .build();
+ }
}
package org.opendaylight.ovsdb.northbound;
+import java.util.Set;
+
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.lib.schema.TableSchema;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
/**
* Northbound interface for OVSDB tables
*/
public class TableResource {
-
+ ObjectMapper objectMapper;
String databaseName;
String nodeId;
TableResource(String nodeId, String databaseName){
this.nodeId = nodeId;
this.databaseName = databaseName;
+ objectMapper = new ObjectMapper();
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ }
+
+ private DatabaseSchema getDatabaseSchema (String databaseName) {
+ OvsdbClient client = NodeResource.getOvsdbConnection(nodeId, this);
+ return client.getDatabaseSchema(databaseName);
}
@GET
@Produces(MediaType.APPLICATION_JSON)
- public Response getTables(){
- return Response.noContent().build();
+ public Response getTables() throws JsonProcessingException {
+ DatabaseSchema dbSchema = this.getDatabaseSchema(databaseName);
+ if (dbSchema == null) {
+ return Response.noContent().build();
+ }
+ String response = objectMapper.writeValueAsString(dbSchema.getTables());
+ return Response.status(Response.Status.OK)
+ .entity(response)
+ .build();
}
@GET
@Path("{name}")
@Produces(MediaType.APPLICATION_JSON)
- public Response getTableDetails(@PathParam("name") String name){
- return Response.noContent().build();
+ public Response getTableDetails(@PathParam("name") String name) throws JsonProcessingException {
+ String csTableName = this.caseSensitiveTableName(databaseName, name);
+ DatabaseSchema dbSchema = this.getDatabaseSchema(databaseName);
+ if (dbSchema == null) {
+ return Response.noContent().build();
+ }
+ TableSchema<GenericTableSchema> tableSchema = dbSchema.table(csTableName, GenericTableSchema.class);
+ String response = objectMapper.writeValueAsString(tableSchema);
+ return Response.status(Response.Status.OK)
+ .entity(response)
+ .build();
}
@Path("{name}/row")
return new RowResource(nodeId, databaseName, name);
}
+ private String caseSensitiveTableName (String databaseName, String ciTableName) {
+ DatabaseSchema dbSchema = this.getDatabaseSchema(databaseName);
+ if (dbSchema == null) {
+ return ciTableName;
+ }
+ Set<String> tables = dbSchema.getTables();
+ if (tables == null) {
+ return ciTableName;
+ }
+ for (String tableName : tables) {
+ if (tableName.equalsIgnoreCase(ciTableName)) return tableName;
+ }
+ return ciTableName;
+ }
}
import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider;
import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
+import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
import org.opendaylight.ovsdb.openstack.netvirt.api.InboundNatProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
import org.opendaylight.ovsdb.openstack.netvirt.api.L3ForwardingProvider;
import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider;
import org.opendaylight.ovsdb.openstack.netvirt.api.OutboundNatProvider;
import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow10.OF10Provider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
c.add(createServiceDependency()
.setService(TenantNetworkManager.class)
.setRequired(true));
+ c.add(createServiceDependency()
+ .setService(SecurityServicesManager.class)
+ .setRequired(true));
c.add(createServiceDependency().setService(OvsdbConfigurationService.class).setRequired(true));
c.add(createServiceDependency().setService(OvsdbConnectionService.class).setRequired(true));
c.add(createServiceDependency().setService(MdsalConsumer.class).setRequired(true));
+ c.add(createServiceDependency().setService(IngressAclProvider.class).setRequired(true));
+ c.add(createServiceDependency().setService(EgressAclProvider.class).setRequired(true));
}
if (imp.equals(PipelineOrchestratorImpl.class)) {
.setCallbacks("registerService", "unregisterService"));
}
- if (AbstractServiceInstance.class.isAssignableFrom((Class)imp)) {
+ if (AbstractServiceInstance.class.isAssignableFrom((Class) imp)) {
c.add(createServiceDependency()
- .setService(PipelineOrchestrator.class)
- .setRequired(true));
+ .setService(PipelineOrchestrator.class)
+ .setRequired(true));
c.add(createServiceDependency().setService(MdsalConsumer.class).setRequired(true));
}
Properties properties = new Properties();
properties.put(AbstractServiceInstance.SERVICE_PROPERTY, Service.INGRESS_ACL);
properties.put(Constants.PROVIDER_NAME_PROPERTY, OF13Provider.NAME);
- c.setInterface(AbstractServiceInstance.class.getName(), properties);
+ c.setInterface(new String[]{AbstractServiceInstance.class.getName(),
+ IngressAclProvider.class.getName()}, properties);
}
if (imp.equals(LoadBalancerService.class)) {
c.setInterface(AbstractServiceInstance.class.getName(), properties);
}
- if (imp.equals(IngressAclService.class)) {
+ if (imp.equals(EgressAclService.class)) {
Properties properties = new Properties();
- properties.put(AbstractServiceInstance.SERVICE_PROPERTY, Service.INGRESS_ACL);
+ properties.put(AbstractServiceInstance.SERVICE_PROPERTY, Service.EGRESS_ACL);
properties.put(Constants.PROVIDER_NAME_PROPERTY, OF13Provider.NAME);
- c.setInterface(AbstractServiceInstance.class.getName(), properties);
+ c.setInterface(new String[]{AbstractServiceInstance.class.getName(),
+ EgressAclProvider.class.getName()}, properties);
}
if (imp.equals(OutboundNatService.class)) {
thread.start();
}
- private NodeBuilder createNodeBuilder(String nodeId) {
+ public NodeBuilder createNodeBuilder(String nodeId) {
NodeBuilder builder = new NodeBuilder();
builder.setId(new NodeId(nodeId));
builder.setKey(new NodeKey(builder.getId()));
*/
package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.ovsdb.lib.notation.Row;
import org.opendaylight.ovsdb.lib.notation.UUID;
-import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
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.EgressAclProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
-import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
-import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
import org.opendaylight.ovsdb.plugin.api.StatusWithUuid;
import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
import org.opendaylight.ovsdb.schema.openvswitch.Interface;
import org.opendaylight.ovsdb.schema.openvswitch.Port;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
+import com.google.common.util.concurrent.CheckedFuture;
/**
* Open vSwitch OpenFlow 1.3 Networking Provider for OpenStack Neutron
private volatile OvsdbConfigurationService ovsdbConfigurationService;
private volatile OvsdbConnectionService connectionService;
private volatile MdsalConsumer mdsalConsumer;
+ private volatile SecurityServicesManager securityServicesManager;
+ private volatile IngressAclProvider ingressAclProvider;
+ private volatile EgressAclProvider egressAclProvider;
public static final String NAME = "OF13Provider";
if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
logger.debug("Program local vlan rules for interface {}", intf.getName());
programLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
- } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
+ }
+ /* If the network type is tunnel based (VXLAN/GRRE/etc) with Neutron Port Security ACLs */
+ if ((networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) || networkType.equalsIgnoreCase
+ (NetworkHandler.NETWORK_TYPE_VXLAN)) && securityServicesManager.isPortSecurityReady(intf)) {
+ logger.debug("Neutron port has a Port Security Group");
+ /* Retrieve the security group UUID from the Neutron Port */
+ NeutronSecurityGroup securityGroupInPort = securityServicesManager.getSecurityGroupInPort(intf);
+ logger.debug("Program Local rules for networkType: {} does contain a Port Security Group: {} " +
+ "to be installed on DPID: {}", networkType, securityGroupInPort, dpid);
+ ingressAclProvider.programPortSecurityACL(node, dpid, segmentationId, attachedMac, localPort,
+ securityGroupInPort);
+ egressAclProvider.programPortSecurityACL(node, dpid, segmentationId, attachedMac, localPort,
+ securityGroupInPort);
+ }
+ else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
logger.debug("Program local bridge rules for interface {}", intf.getName());
programLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
*/
package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
+import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+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.yang.types.rev100924.MacAddress;
+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.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.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+
+import com.google.common.collect.Lists;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.List;
+
+public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider {
+
+ static final Logger logger = LoggerFactory.getLogger(EgressAclService.class);
-public class EgressAclService extends AbstractServiceInstance {
public EgressAclService() {
super(Service.EGRESS_ACL);
}
super(service);
}
+
@Override
public boolean isBridgeInPipeline (String nodeId) {
return true;
}
-}
\ No newline at end of file
+
+ @Override
+ public void programPortSecurityACL(Node node, Long dpid, String segmentationId, String attachedMac, long localPort,
+ NeutronSecurityGroup securityGroup) {
+
+ logger.trace("programLocalBridgeRulesWithSec neutronSecurityGroup: {} ", securityGroup);
+ List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
+ /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
+ for (NeutronSecurityRule portSecurityRule : portSecurityList) {
+ /**
+ * Neutron Port Security ACL "egress" and "IPv4"
+ *
+ * Check that the base conditions for flow based Port Security are true:
+ * Port Security Rule Direction ("egress") and Protocol ("IPv4")
+ * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
+ * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
+ *
+ */
+ if (portSecurityRule.getSecurityRuleEthertype().equalsIgnoreCase("IPv4") &&
+ portSecurityRule.getSecurityRuleDirection().equalsIgnoreCase("egress")) {
+ logger.debug("Egress IPV4 ACL Port Security Rule: {} ", portSecurityRule);
+ // ToDo: Implement Port Range
+
+ /**
+ * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (True)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
+ .equalsIgnoreCase("0.0.0.0/0"))) {
+ logger.debug(
+ "Rule #1 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
+ Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
+ true);
+ egressACLTcpPortWithPrefix(dpid, segmentationId,
+ attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix(),
+ Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (True)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
+ .equalsIgnoreCase("0.0.0.0/0"))) {
+ logger.debug(
+ "Rule #2 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
+ Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
+ true);
+ egressACLTcpPortWithPrefix(dpid, segmentationId,
+ attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix(),
+ Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
+ logger.debug(
+ "Rule #3 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PREFIX_MATCH_PRIORITY_DROP,
+ true);
+ egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
+ portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PROTO_PREFIX_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (False), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
+ .equalsIgnoreCase("0.0.0.0/0"))) {
+ logger.debug(
+ "Rule #4 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PREFIX_MATCH_PRIORITY_DROP, true);
+ egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
+ portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PREFIX_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (False)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
+ logger.debug(
+ "Rule #5 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PORT_MATCH_PRIORITY_DROP,
+ true);
+ egressACLTcpSyn(dpid, segmentationId,
+ attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
+ Constants.PROTO_PORT_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (False)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
+ logger.debug(
+ "Rule #6 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
+ Constants.PROTO_PORT_MATCH_PRIORITY_DROP, true);
+ egressACLTcpSyn(dpid, segmentationId, attachedMac, true,
+ portSecurityRule.getSecurityRulePortMin(), Constants.PROTO_PORT_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (False or 0.0.0.0/0)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ ((String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) ||
+ String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
+ .equalsIgnoreCase("0.0.0.0/0"))) {
+ logger.debug(
+ "Rule #7 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ // No need to drop until UDP/ICMP are implemented
+ // egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_MATCH_PRIORITY_DROP, true);
+ egressAllowProto(dpid, segmentationId, attachedMac, true,
+ portSecurityRule.getSecurityRuleProtocol(), Constants.PROTO_MATCH_PRIORITY);
+ continue;
+ }
+ logger.debug("ACL Match combination not found for rule: {}", portSecurityRule);
+ }
+ }
+ }
+
+ public void egressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
+ int priority, boolean write) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils.createSmacTcpPortWithFlagMatch(matchBuilder,
+ attachedMac, Constants.TCP_SYN, segmentationId).build());
+ logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
+
+ String flowId = "TCP_Syn_Egress_Default_Drop_" + attachedMac;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(priority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+
+ InstructionUtils.createDropInstructions(ib);
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+ // Add InstructionBuilder to the Instruction(s)Builder List
+ isb.setInstruction(instructions);
+
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ public void egressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac, boolean write,
+ Integer securityRulePortMin, String securityRuleIpPrefix, Integer protoPortPrefixMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ PortNumber tcpPort = new PortNumber(securityRulePortMin);
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
+
+ flowBuilder.setMatch(MatchUtils
+ .createSmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
+ tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
+
+ logger.debug(" MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "UcastEgress_" + segmentationId + "_" + attachedMac +
+ securityRulePortMin + securityRuleIpPrefix;
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortPrefixMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+
+
+ public void egressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
+ String securityRuleProtcol, Integer protoMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils
+ .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
+ flowBuilder.setMatch(MatchUtils
+ .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+
+ logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "EgressAllProto_" + segmentationId + "_" +
+ attachedMac + "_AllowEgressTCPSyn_" + securityRuleProtcol;
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ public void egressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
+ boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
+ .build());
+ if (securityRuleIpPrefix != null) {
+ flowBuilder.setMatch(MatchUtils
+ .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
+ .build());
+ } else {
+ flowBuilder.setMatch(MatchUtils
+ .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
+ .build());
+ }
+ logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "Egress_Proto_ACL" + segmentationId + "_" +
+ attachedMac + "_Permit_" + securityRuleIpPrefix;
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+
+ public void egressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
+ Integer securityRulePortMin, Integer protoPortMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ PortNumber tcpPort = new PortNumber(securityRulePortMin);
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils.createSmacTcpSyn(matchBuilder, attachedMac, tcpPort,
+ Constants.TCP_SYN, segmentationId).build());
+
+ logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "Ucast_this.getTable()" + segmentationId + "_" + attachedMac + securityRulePortMin;
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+}
*/
package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
+import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+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.yang.types.rev100924.MacAddress;
+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.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.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+public class IngressAclService extends AbstractServiceInstance implements IngressAclProvider {
+
+ static final Logger logger = LoggerFactory.getLogger(IngressAclService.class);
-public class IngressAclService extends AbstractServiceInstance {
public IngressAclService() {
super(Service.INGRESS_ACL);
}
}
@Override
- public boolean isBridgeInPipeline (String nodeId) {
+ public boolean isBridgeInPipeline(String nodeId) {
return true;
}
-}
\ No newline at end of file
+
+ @Override
+ public void programPortSecurityACL(Node node, Long dpid, String segmentationId, String attachedMac,
+ long localPort, NeutronSecurityGroup securityGroup) {
+
+ logger.trace("programLocalBridgeRulesWithSec neutronSecurityGroup: {} ", securityGroup);
+ List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
+ /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
+ for (NeutronSecurityRule portSecurityRule : portSecurityList) {
+ /**
+ * Neutron Port Security ACL "ingress" and "IPv4"
+ *
+ * Check that the base conditions for flow based Port Security are true:
+ * Port Security Rule Direction ("ingress") and Protocol ("IPv4")
+ * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
+ * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
+ *
+ */
+ if (portSecurityRule.getSecurityRuleEthertype().equalsIgnoreCase("IPv4") &&
+ portSecurityRule.getSecurityRuleDirection().equalsIgnoreCase("ingress")) {
+ logger.debug("ACL Rule matching IPv4 and ingress is: {} ", portSecurityRule);
+ /**
+ * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (True)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
+ .equalsIgnoreCase("0.0.0.0/0"))) {
+ logger.debug("Rule #1 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
+ Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
+ true);
+ ingressACLTcpPortWithPrefix(dpid, segmentationId,
+ attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (True)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
+ .equalsIgnoreCase("0.0.0.0/0"))) {
+ logger.debug("Rule #2 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
+ Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
+ true);
+ ingressACLTcpPortWithPrefix(dpid, segmentationId,
+ attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
+ logger.debug("Rule #3 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PREFIX_MATCH_PRIORITY_DROP,
+ true);
+ ingressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
+ portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PROTO_PREFIX_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (False), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
+ .equalsIgnoreCase("0.0.0.0/0"))) {
+ logger.debug("Rule #4 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PREFIX_MATCH_PRIORITY_DROP, true);
+ ingressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
+ portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PREFIX_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (False)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
+ logger.debug("Rule #5 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PORT_MATCH_PRIORITY_DROP,
+ true);
+ ingressACLTcpSyn(dpid, segmentationId,
+ attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
+ Constants.PREFIX_PORT_MATCH_PRIORITY_DROP);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (False)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
+ logger.debug("Rule #6 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
+ Constants.PROTO_PORT_MATCH_PRIORITY_DROP, true);
+ ingressACLTcpSyn(dpid, segmentationId, attachedMac, true,
+ portSecurityRule.getSecurityRulePortMin(), Constants.PROTO_PORT_MATCH_PRIORITY);
+ continue;
+ }
+ /**
+ * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (False or 0.0.0.0/0)
+ */
+ if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
+ String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
+ ((String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) ||
+ String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
+ .equalsIgnoreCase("0.0.0.0/0"))) {
+ logger.debug("Rule #7 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
+ portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
+ portSecurityRule.getSecurityRulePortMax(),
+ portSecurityRule.getSecurityRuleRemoteIpPrefix());
+ // No need to drop until UDP/ICMP are implemented
+ // ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_MATCH_PRIORITY_DROP, true);
+ handleIngressAllowProto(dpid, segmentationId, attachedMac, true,
+ portSecurityRule.getSecurityRuleProtocol(), Constants.PROTO_MATCH_PRIORITY);
+ continue;
+ }
+ logger.debug("Ingress ACL Match combination not found for rule: {}", portSecurityRule);
+ }
+ }
+ }
+
+ public void ingressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
+ Integer securityRulePortMin, Integer protoPortMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ PortNumber tcpPort = new PortNumber(securityRulePortMin);
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils.createDmacTcpSynMatch(matchBuilder, attachedMac, tcpPort,
+ Constants.TCP_SYN, segmentationId).build());
+
+ logger.debug("ingressACLTcpSyn MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "UcastOut_ACL2" + segmentationId + "_" + attachedMac + securityRulePortMin;
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("Instructions are: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ public void ingressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac,
+ boolean write, Integer securityRulePortMin, String securityRuleIpPrefix,
+ Integer protoPortPrefixMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ PortNumber tcpPort = new PortNumber(securityRulePortMin);
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = this.createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
+
+ flowBuilder.setMatch(MatchUtils
+ .createDmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
+ tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
+
+ logger.debug(" MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "UcastOut2_" + segmentationId + "_" + attachedMac +
+ securityRulePortMin + securityRuleIpPrefix;
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortPrefixMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+
+ List<Instruction> instructionsList = Lists.newArrayList();
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ public void handleIngressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
+ String securityRuleProtcol, Integer protoMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils
+ .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
+ flowBuilder.setMatch(MatchUtils
+ .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+ logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
+
+ String flowId = "UcastOut_" + segmentationId + "_" +
+ attachedMac + "_AllowTCPSynPrefix_" + securityRuleProtcol;
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(1);
+ ib.setKey(new InstructionKey(1));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+
+ public void ingressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
+ int priority, boolean write) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils.createDmacTcpPortWithFlagMatch(matchBuilder,
+ attachedMac, Constants.TCP_SYN, segmentationId).build());
+
+ logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "PortSec_TCP_Syn_Default_Drop_" + attachedMac;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(priority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+
+ // Instructions List Stores Individual Instructions
+ List<Instruction> instructions = Lists.newArrayList();
+
+ // Set the Output Port/Iface
+ InstructionUtils.createDropInstructions(ib);
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ // Add InstructionBuilder to the Instruction(s)Builder List
+ isb.setInstruction(instructions);
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ public void ingressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
+ boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
+
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+ Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
+ .build());
+ if (securityRuleIpPrefix != null) {
+ flowBuilder.setMatch(MatchUtils
+ .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
+ .build());
+ } else {
+ flowBuilder.setMatch(MatchUtils
+ .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
+ .build());
+ }
+
+ logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
+ String flowId = "IngressProto_ACL_" + segmentationId + "_" +
+ attachedMac + "_Permit_" + securityRuleIpPrefix;
+ // Add Flow Attributes
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(false);
+ flowBuilder.setPriority(protoPortMatchPriority);
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(this.getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(1);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+
+ logger.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+}
import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.OutboundNatProvider;
import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.VlanConfigurationCache;
import org.opendaylight.ovsdb.openstack.netvirt.impl.BridgeConfigurationManagerImpl;
import org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter;
import org.opendaylight.ovsdb.openstack.netvirt.impl.OpenstackRouter;
import org.opendaylight.ovsdb.openstack.netvirt.impl.ProviderNetworkManagerImpl;
+import org.opendaylight.ovsdb.openstack.netvirt.impl.SecurityServicesImpl;
import org.opendaylight.ovsdb.openstack.netvirt.impl.TenantNetworkManagerImpl;
import org.opendaylight.ovsdb.openstack.netvirt.impl.VlanConfigurationCacheImpl;
import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
LBaaSHandler.class,
LBaaSPoolMemberHandler.class,
NeutronL3Adapter.class,
- OpenstackRouter.class};
+ OpenstackRouter.class,
+ SecurityServicesImpl.class};
return res;
}
Properties portSecurityHandlerProperties = new Properties();
portSecurityHandlerProperties.put(Constants.EVENT_HANDLER_TYPE_PROPERTY,
AbstractEvent.HandlerType.NEUTRON_PORT_SECURITY);
- c.setInterface(new String[] {INeutronSecurityRuleAware.class.getName(),
- INeutronSecurityGroupAware.class.getName(),
- AbstractHandler.class.getName()},
+ c.setInterface(new String[]{INeutronSecurityRuleAware.class.getName(),
+ INeutronSecurityGroupAware.class.getName(),
+ AbstractHandler.class.getName()},
portSecurityHandlerProperties);
c.add(createServiceDependency().setService(EventDispatcher.class).setRequired(true));
+ c.add(createServiceDependency().setService(SecurityServicesManager.class).setRequired(true));
+ }
+
+ if (imp.equals(SecurityServicesImpl.class)) {
+ c.setInterface(new String[] {SecurityServicesManager.class.getName()}, null);
}
if (imp.equals(FWaasHandler.class)) {
* Ethertypes
*/
public static final long ARP_ETHERTYPE = 0x0806L;
+
+
+ /*
+ * ACL
+ */
+ public static final Integer PROTO_MATCH_PRIORITY_DROP = 36006;
+ public static final Integer PROTO_PORT_MATCH_PRIORITY_DROP = 36005;
+ public static final Integer PREFIX_MATCH_PRIORITY_DROP = 36004;
+ public static final Integer PROTO_PREFIX_MATCH_PRIORITY_DROP = 36003;
+ public static final Integer PREFIX_PORT_MATCH_PRIORITY_DROP = 36002;
+ public static final Integer PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP = 36001;
+
+ public static final Integer PROTO_MATCH_PRIORITY = 61010;
+ public static final Integer PREFIX_MATCH_PRIORITY = 61009;
+ public static final Integer PROTO_PREFIX_MATCH_PRIORITY = 61008;
+ public static final Integer PROTO_PORT_MATCH_PRIORITY = 61007;
+ public static final Integer PROTO_PORT_PREFIX_MATCH_PRIORITY = 61007;
+
+ public static final int TCP_SYN = 0x002;
+ public static final short INGRESS_ACL = 40; // Flows Destined to the VM Port go here
+ public static final short OUTBOUND_SNAT = 110; // Ingress ACL table drains traffic to this table
+
+ private static Long groupId = 1L;
}
--- /dev/null
+package org.opendaylight.ovsdb.openstack.netvirt.api;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.controller.sal.core.Node;
+
+/**
+ * This interface allows egress Port Security flows to be written to devices
+ */
+public interface EgressAclProvider {
+
+ /**
+ * Program port security ACL.
+ *
+ * @param node the node
+ * @param dpid the dpid
+ * @param segmentationId the segmentation id
+ * @param attachedMac the attached mac
+ * @param localPort the local port
+ * @param securityGroup the security group
+ */
+ public void programPortSecurityACL(Node node, Long dpid, String segmentationId, String attachedMac,
+ long localPort, NeutronSecurityGroup securityGroup);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 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
+ *
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.api;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.controller.sal.core.Node;
+
+/**
+ * This interface allows ingress Port Security flows to be written to devices
+ */
+public interface IngressAclProvider {
+
+ /**
+ * Program port security ACL.
+ *
+ * @param node the node
+ * @param dpid the dpid
+ * @param segmentationId the segmentation id
+ * @param attachedMac the attached mac
+ * @param localPort the local port
+ * @param securityGroup the security group
+ */
+ public void programPortSecurityACL(Node node, Long dpid, String segmentationId, String attachedMac,
+ long localPort, NeutronSecurityGroup securityGroup);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 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
+ *
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.api;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.ovsdb.schema.openvswitch.Interface;
+
+/**
+ * Open vSwitch isolates Tenant Networks using VLANs on the Integration Bridge
+ * This class manages the provisioning of these VLANs
+ */
+public interface SecurityServicesManager {
+ /**
+ * Is port security ready.
+ *
+ * @param intf the intf
+ * @return the boolean
+ */
+ public boolean isPortSecurityReady(Interface intf);
+ /**
+ * Gets security group in port.
+ *
+ * @param intf the intf
+ * @return the security group in port
+ */
+ public NeutronSecurityGroup getSecurityGroupInPort(Interface intf);
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 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
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.impl;
+
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
+import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
+
+import org.opendaylight.ovsdb.schema.openvswitch.Interface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Map;
+
+public class SecurityServicesImpl implements SecurityServicesManager {
+
+ static final Logger logger = LoggerFactory.getLogger(TenantNetworkManagerImpl.class);
+
+ public SecurityServicesImpl() {
+ }
+
+ /**
+ * Is security group ready.
+ *
+ * @param intf the intf
+ * @return the boolean
+ */
+ public boolean isPortSecurityReady(Interface intf) {
+ logger.trace("getTenantNetworkForInterface for {}", intf);
+ if (intf == null) return false;
+ Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
+ logger.trace("externalIds {}", externalIds);
+ if (externalIds == null) return false;
+ String neutronPortId = externalIds.get(Constants.EXTERNAL_ID_INTERFACE_ID);
+ if (neutronPortId == null) return false;
+ INeutronPortCRUD neutronPortService = (INeutronPortCRUD) ServiceHelper.getGlobalInstance(INeutronPortCRUD.class,
+ this);
+ NeutronPort neutronPort = neutronPortService.getPort(neutronPortId);
+ String deviceOwner = neutronPort.getDeviceOwner();
+ if (!deviceOwner.contains("compute")) {
+ logger.debug("Port {} is not a compute host, it is a: {}", neutronPortId, deviceOwner);
+ }
+ logger.debug("isPortSecurityReady() is a {} ", deviceOwner);
+ List<NeutronSecurityGroup> securityGroups = neutronPort.getSecurityGroups();
+ if (securityGroups.isEmpty()) {
+ logger.debug("Check for device: {} does not contain a Security Group for port: {}", deviceOwner,
+ neutronPortId);
+ return false;
+ }
+ try {
+ String vmPort = externalIds.get("attached-mac");
+ } catch(Exception e) {
+ logger.debug("Error VMID did *NOT* work");
+ }
+ logger.debug("Security Group Check {} DOES contain a Neutron Security Group", neutronPortId);
+ return true;
+ }
+
+ /**
+ * Gets security group in port.
+ *
+ * @param intf the intf
+ * @return the security group in port
+ */
+ public NeutronSecurityGroup getSecurityGroupInPort(Interface intf) {
+ logger.trace("getTenantNetworkForInterface for {}", intf);
+ if (intf == null) return null;
+ Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
+ logger.trace("externalIds {}", externalIds);
+ if (externalIds == null) return null;
+ String neutronPortId = externalIds.get(Constants.EXTERNAL_ID_INTERFACE_ID);
+ if (neutronPortId == null) return null;
+ INeutronPortCRUD neutronPortService = (INeutronPortCRUD)
+ ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, this);
+ NeutronPort neutronPort = neutronPortService.getPort(neutronPortId);
+ List<NeutronSecurityGroup> neutronSecurityGroups = neutronPort.getSecurityGroups();
+ NeutronSecurityGroup neutronSecurityGroup = (NeutronSecurityGroup) neutronSecurityGroups.toArray()[0];
+ return neutronSecurityGroup;
+ }
+}
@Deprecated
public Status updateRow (Node node, String tableName, String parentUUID, String rowUUID, Row row) {
String databaseName = OvsVswitchdSchemaConstants.DATABASE_NAME;
- Connection connection = connectionService.getConnection(node);
- OvsdbClient client = connection.getClient();
-
- logger.debug("updateRow : Connection : {} databaseName : {} tableName : {} rowUUID : {} row : {}",
- client.getConnectionInfo(), databaseName, tableName, rowUUID, row.toString());
- try{
- DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
- TransactionBuilder transactionBuilder = client.transactBuilder(dbSchema);
- TableSchema<GenericTableSchema> tableSchema = dbSchema.table(tableName, GenericTableSchema.class);
- ColumnSchema<GenericTableSchema, UUID> _uuid = tableSchema.column("_uuid", UUID.class);
- transactionBuilder.add(op.update(tableSchema, row)
- .where(_uuid.opEqual(new UUID(rowUUID)))
- .build());
-
- ListenableFuture<List<OperationResult>> results = transactionBuilder.execute();
- List<OperationResult> operationResults = results.get();
- if (operationResults.isEmpty() || (transactionBuilder.getOperations().size() != operationResults.size())) {
- return new StatusWithUuid(StatusCode.INTERNALERROR);
- }
- for (OperationResult result : operationResults) {
- if (result.getError() != null) {
- return new StatusWithUuid(StatusCode.BADREQUEST, result.getError());
- }
- }
- return new StatusWithUuid(StatusCode.SUCCESS);
- } catch(Exception e){
- logger.error("Error in updateRow(): ",e);
- }
- return new Status(StatusCode.INTERNALERROR);
+ Row<GenericTableSchema> updatedRow = this.updateRow(node, databaseName, tableName, new UUID(rowUUID), row, true);
+ return new StatusWithUuid(StatusCode.SUCCESS);
}
private void processDeleteTransaction(OvsdbClient client, String databaseName, String childTable,
@Override
@Deprecated
public List<String> getTables(Node node) {
- ConcurrentMap<String, ConcurrentMap<String, Row>> cache = ovsdbInventoryService.getCache(node, OvsVswitchdSchemaConstants.DATABASE_NAME);
- if (cache == null) return null;
- return new ArrayList<String>(cache.keySet());
+ return this.getTables(node, OvsVswitchdSchemaConstants.DATABASE_NAME);
}
private List<InetAddress> getControllerIPAddresses(Connection connection) {
public Row<GenericTableSchema> updateRow(Node node, String databaseName,
String tableName, UUID rowUuid, Row<GenericTableSchema> row,
boolean overwrite) throws OvsdbPluginException {
- throw new OvsdbPluginException("Not implemented Yet");
+ Connection connection = connectionService.getConnection(node);
+ OvsdbClient client = connection.getClient();
+
+ logger.debug("updateRow : Connection : {} databaseName : {} tableName : {} rowUUID : {} row : {}",
+ client.getConnectionInfo(), databaseName, tableName, rowUuid, row.toString());
+ try{
+ DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
+ TransactionBuilder transactionBuilder = client.transactBuilder(dbSchema);
+ TableSchema<GenericTableSchema> tableSchema = dbSchema.table(tableName, GenericTableSchema.class);
+ ColumnSchema<GenericTableSchema, UUID> _uuid = tableSchema.column("_uuid", UUID.class);
+ transactionBuilder.add(op.update(tableSchema, row)
+ .where(_uuid.opEqual(rowUuid))
+ .build());
+
+ ListenableFuture<List<OperationResult>> results = transactionBuilder.execute();
+ List<OperationResult> operationResults = results.get();
+ for (OperationResult result : operationResults) {
+ if (result.getError() != null) {
+ throw new OvsdbPluginException("Error updating row : "+ result.getError());
+ }
+ }
+ if (operationResults.isEmpty() || (transactionBuilder.getOperations().size() != operationResults.size())) {
+ throw new OvsdbPluginException("Failed to update row. Please check OVS logs for more info.");
+ }
+
+ return this.getRow(node, databaseName, tableName, rowUuid);
+ } catch(Exception e){
+ throw new OvsdbPluginException("Error updating row due to an exception "+ e.getMessage());
+ }
}
@Override
public void deleteRow(Node node, String databaseName, String tableName, String parentTable, UUID parentRowUuid,
String parentColumn, UUID rowUuid) throws OvsdbPluginException {
- throw new OvsdbPluginException("Not implemented Yet");
+ Connection connection = connectionService.getConnection(node);
+ OvsdbClient client = connection.getClient();
+
+ if (parentTable == null && parentRowUuid != null) {
+ parentTable = this.getTableNameForRowUuid(node, databaseName, parentRowUuid);
+ }
+
+ if (parentColumn == null && parentTable != null) {
+ DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
+ TableSchema<GenericTableSchema> parentTableSchema = dbSchema.table(parentTable, GenericTableSchema.class);
+ parentColumn = this.getReferencingColumn(parentTableSchema, tableName);
+ }
+
+ logger.debug("deleteRow : Connection : {} databaseName : {} tableName : {} Uuid : {} ParentTable : {} ParentColumn : {}",
+ client.getConnectionInfo(), databaseName, tableName, rowUuid, parentTable, parentColumn);
+
+ DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
+ TransactionBuilder transactionBuilder = client.transactBuilder(dbSchema);
+ this.processDeleteTransaction(client, databaseName, tableName,
+ parentTable, parentColumn, rowUuid.toString(), transactionBuilder);
+
+ ListenableFuture<List<OperationResult>> results = transactionBuilder.execute();
+ List<OperationResult> operationResults;
+ try {
+ operationResults = results.get();
+ if (operationResults.isEmpty() || (transactionBuilder.getOperations().size() != operationResults.size())) {
+ throw new OvsdbPluginException("Delete Operation Failed");
+ }
+ for (OperationResult result : operationResults) {
+ if (result.getError() != null) {
+ throw new OvsdbPluginException("Delete Operation Failed with Error : "+result.getError().toString());
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
@Override
- public void deleteRow(Node node, String databaseName, String tableName,
- UUID rowUuid) throws OvsdbPluginException {
- throw new OvsdbPluginException("Not implemented Yet");
+ public void deleteRow(Node node, String databaseName, String tableName, UUID rowUuid) throws OvsdbPluginException {
+ this.deleteRow(node, databaseName, tableName, null, null, null, rowUuid);
}
@Override
public Row<GenericTableSchema> getRow(Node node, String databaseName,
String tableName, UUID uuid) throws OvsdbPluginException {
- throw new OvsdbPluginException("Not implemented Yet");
+ ConcurrentMap<UUID, Row<GenericTableSchema>> rows = this.getRows(node, databaseName, tableName);
+ if (rows != null) {
+ return rows.get(uuid);
+ }
+ return null;
}
@Override
public ConcurrentMap<UUID, Row<GenericTableSchema>> getRows(Node node,
String databaseName, String tableName) throws OvsdbPluginException {
- throw new OvsdbPluginException("Not implemented Yet");
+ ConcurrentMap<String, Row> ovsTable = ovsdbInventoryService.getTableCache(node, databaseName, tableName);
+ if (ovsTable == null) return null;
+ ConcurrentMap<UUID, Row<GenericTableSchema>> tableDB = Maps.newConcurrentMap();
+ for (String uuidStr : ovsTable.keySet()) {
+ tableDB.put(new UUID(uuidStr), ovsTable.get(uuidStr));
+ }
+ return tableDB;
}
@Override
public ConcurrentMap<UUID, Row<GenericTableSchema>> getRows(Node node,
String databaseName, String tableName, String fiqlQuery)
throws OvsdbPluginException {
- throw new OvsdbPluginException("Not implemented Yet");
+ return this.getRows(node, databaseName, tableName);
}
@Override
public List<String> getTables(Node node, String databaseName) throws OvsdbPluginException {
- throw new OvsdbPluginException("Not implemented Yet");
+ ConcurrentMap<String, ConcurrentMap<String, Row>> cache = ovsdbInventoryService.getCache(node, databaseName);
+ if (cache == null) return null;
+ return new ArrayList<String>(cache.keySet());
}
-}
-
+}
\ No newline at end of file
<!-- Karaf Distribution -->
<module>features/ovsdb</module>
<module>features/of-nxm-extensions</module>
+ <module>features/ovs-sfc</module>
<!-- OVSDB Distribution -->
<module>distribution/opendaylight</module>
</modules>
public class MatchUtils {
private static final Logger logger = LoggerFactory.getLogger(MatchUtils.class);
+ public static final short ICMP_SHORT = 1;
+ public static final short TCP_SHORT = 6;
+ public static final short UDP_SHORT = 17;
+ public static final String TCP = "tcp";
+ public static final String UDP = "udp";
+ private static final int TCP_SYN = 0x0002;
/**
* Create Ingress Port Match dpidLong, inPort
return matchBuilder;
}
+ /**
+ * Create TCP Port Match
+ *
+ * @param matchBuilder @param matchbuilder MatchBuilder Object without a match yet
+ * @param tcpport Integer representing a source TCP port
+ * @return matchBuilder Map MatchBuilder Object with a match
+ */
+ public static MatchBuilder createIpProtocolMatch(MatchBuilder matchBuilder, short ipProtocol) {
+
+ EthernetMatchBuilder ethType = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethType.setEthernetType(ethTypeBuilder.build());
+ matchBuilder.setEthernetMatch(ethType.build());
+
+ IpMatchBuilder ipMmatch = new IpMatchBuilder();
+ if (ipProtocol == TCP_SHORT) {
+ ipMmatch.setIpProtocol(TCP_SHORT);
+ }
+ else if (ipProtocol == UDP_SHORT) {
+ ipMmatch.setIpProtocol(UDP_SHORT);
+ }
+ else if (ipProtocol == ICMP_SHORT) {
+ ipMmatch.setIpProtocol(ICMP_SHORT);
+ }
+ matchBuilder.setIpMatch(ipMmatch.build());
+ return matchBuilder;
+ }
+
+ /**
+ * Create tcp syn with proto match.
+ *
+ * @param matchBuilder the match builder
+ * @return matchBuilder match builder
+ */
+ public static MatchBuilder createTcpSynWithProtoMatch(MatchBuilder matchBuilder) {
+
+ // Ethertype match
+ EthernetMatchBuilder ethernetType = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetType.setEthernetType(ethTypeBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetType.build());
+
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol((short) 6);
+ matchBuilder.setIpMatch(ipMatch.build());
+
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(TCP_SYN);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+ return matchBuilder;
+ }
+
+ /**
+ * Create tcp proto syn match.
+ *
+ * @param matchBuilder the match builder
+ * @return matchBuilder match builder
+ */
+ public static MatchBuilder createTcpProtoSynMatch(MatchBuilder matchBuilder) {
+
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol((short) 6);
+ matchBuilder.setIpMatch(ipMatch.build());
+
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(TCP_SYN);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+ return matchBuilder;
+ }
+
+ /**
+ * Create dmac tcp port with flag match.
+ *
+ * @param matchBuilder the match builder
+ * @param attachedMac the attached mac
+ * @param tcpFlag the tcp flag
+ * @param tunnelID the tunnel iD
+ * @return match containing TCP_Flag (), IP Protocol (TCP), TCP_Flag (SYN)
+ */
+ public static MatchBuilder createDmacTcpPortWithFlagMatch(MatchBuilder matchBuilder,
+ String attachedMac, Integer tcpFlag, String tunnelID) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetMatch.setEthernetType(ethTypeBuilder.build());
+
+ EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder();
+ ethDestinationBuilder.setAddress(new MacAddress(attachedMac));
+ ethernetMatch.setEthernetDestination(ethDestinationBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol(TCP_SHORT);
+ matchBuilder.setIpMatch(ipMatch.build());
+
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(tcpFlag);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+
+ TunnelBuilder tunnelBuilder = new TunnelBuilder();
+ tunnelBuilder.setTunnelId(new BigInteger(tunnelID));
+ matchBuilder.setTunnel(tunnelBuilder.build());
+
+ return matchBuilder;
+ }
+
+ /**
+ * Create dmac tcp syn match.
+ *
+ * @param matchBuilder the match builder
+ * @param attachedMac the attached mac
+ * @param tcpPort the tcp port
+ * @param tcpFlag the tcp flag
+ * @param tunnelID the tunnel iD
+ * @return the match builder
+ */
+ public static MatchBuilder createDmacTcpSynMatch(MatchBuilder matchBuilder,
+ String attachedMac, PortNumber tcpPort, Integer tcpFlag, String tunnelID) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetMatch.setEthernetType(ethTypeBuilder.build());
+
+ EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder();
+ ethDestinationBuilder.setAddress(new MacAddress(attachedMac));
+ ethernetMatch.setEthernetDestination(ethDestinationBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol((short) 6);
+ matchBuilder.setIpMatch(ipMatch.build());
+
+ // TCP Port Match
+ PortNumber dstPort = new PortNumber(tcpPort);
+ TcpMatchBuilder tcpMatch = new TcpMatchBuilder();
+ tcpMatch.setTcpDestinationPort(dstPort);
+ matchBuilder.setLayer4Match(tcpMatch.build());
+
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(tcpFlag);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+
+ TunnelBuilder tunnelBuilder = new TunnelBuilder();
+ tunnelBuilder.setTunnelId(new BigInteger(tunnelID));
+ matchBuilder.setTunnel(tunnelBuilder.build());
+
+ return matchBuilder;
+ }
+
+ /**
+ * Create dmac tcp syn dst ip prefix tcp port.
+ *
+ * @param matchBuilder the match builder
+ * @param attachedMac the attached mac
+ * @param tcpPort the tcp port
+ * @param tcpFlag the tcp flag
+ * @param segmentationId the segmentation id
+ * @param dstIp the dst ip
+ * @return the match builder
+ */
+ public static MatchBuilder createDmacTcpSynDstIpPrefixTcpPort(MatchBuilder matchBuilder,
+ MacAddress attachedMac, PortNumber tcpPort, Integer tcpFlag, String segmentationId,
+ Ipv4Prefix dstIp) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetMatch.setEthernetType(ethTypeBuilder.build());
+
+ EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder();
+ ethDestinationBuilder.setAddress(new MacAddress(attachedMac));
+ ethernetMatch.setEthernetDestination(ethDestinationBuilder.build());
+
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+ Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
+ ipv4match.setIpv4Destination(dstIp);
+ matchBuilder.setLayer3Match(ipv4match.build());
+
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol(TCP_SHORT);
+ matchBuilder.setIpMatch(ipMatch.build());
+
+ // TCP Port Match
+ PortNumber dstPort = new PortNumber(tcpPort);
+ TcpMatchBuilder tcpMatch = new TcpMatchBuilder();
+ tcpMatch.setTcpDestinationPort(dstPort);
+ matchBuilder.setLayer4Match(tcpMatch.build());
+
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(tcpFlag);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+
+ TunnelBuilder tunnelBuilder = new TunnelBuilder();
+ tunnelBuilder.setTunnelId(new BigInteger(segmentationId));
+ matchBuilder.setTunnel(tunnelBuilder.build());
+
+ return matchBuilder;
+ }
+
+ /**
+ * Create dmac ip tcp syn match.
+ *
+ * @param matchBuilder the match builder
+ * @param dMacAddr the d mac addr
+ * @param mask the mask
+ * @param ipPrefix the ip prefix
+ * @return MatchBuilder containing the metadata match values
+ */
+ public static MatchBuilder createDmacIpTcpSynMatch(MatchBuilder matchBuilder,
+ MacAddress dMacAddr, MacAddress mask, Ipv4Prefix ipPrefix) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetDestinationBuilder ethDestBuilder = new EthernetDestinationBuilder();
+ ethDestBuilder.setAddress(new MacAddress(dMacAddr));
+ if (mask != null) {
+ ethDestBuilder.setMask(mask);
+ }
+ ethernetMatch.setEthernetDestination(ethDestBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+ // Ethertype match
+ EthernetMatchBuilder ethernetType = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetType.setEthernetType(ethTypeBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetType.build());
+ if (ipPrefix != null) {
+ Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
+ ipv4match.setIpv4Destination(ipPrefix);
+ matchBuilder.setLayer3Match(ipv4match.build());
+ }
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol(TCP_SHORT);
+ matchBuilder.setIpMatch(ipMatch.build());
+ // TCP Flag Match
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(TCP_SYN);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+
+ return matchBuilder;
+ }
+
+ /**
+ * Create smac tcp syn dst ip prefix tcp port.
+ *
+ * @param matchBuilder the match builder
+ * @param attachedMac the attached mac
+ * @param tcpPort the tcp port
+ * @param tcpFlag the tcp flag
+ * @param segmentationId the segmentation id
+ * @param dstIp the dst ip
+ * @return the match builder
+ */
+ public static MatchBuilder createSmacTcpSynDstIpPrefixTcpPort(MatchBuilder matchBuilder, MacAddress attachedMac,
+ PortNumber tcpPort, Integer tcpFlag, String segmentationId, Ipv4Prefix dstIp) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetMatch.setEthernetType(ethTypeBuilder.build());
+
+ EthernetSourceBuilder ethSourceBuilder = new EthernetSourceBuilder();
+ ethSourceBuilder.setAddress(new MacAddress(attachedMac));
+ ethernetMatch.setEthernetSource(ethSourceBuilder.build());
+
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+ Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
+ ipv4match.setIpv4Destination(dstIp);
+ matchBuilder.setLayer3Match(ipv4match.build());
+
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol(TCP_SHORT);
+ matchBuilder.setIpMatch(ipMatch.build());
+
+ // TCP Port Match
+ PortNumber dstPort = new PortNumber(tcpPort);
+ TcpMatchBuilder tcpMatch = new TcpMatchBuilder();
+ tcpMatch.setTcpDestinationPort(dstPort);
+ matchBuilder.setLayer4Match(tcpMatch.build());
+
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(tcpFlag);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+
+ TunnelBuilder tunnelBuilder = new TunnelBuilder();
+ tunnelBuilder.setTunnelId(new BigInteger(segmentationId));
+ matchBuilder.setTunnel(tunnelBuilder.build());
+
+ return matchBuilder;
+ }
+
+ /**
+ * Create smac tcp port with flag match.
+ *
+ * @param matchBuilder the match builder
+ * @param attachedMac the attached mac
+ * @param tcpFlag the tcp flag
+ * @param tunnelID the tunnel iD
+ * @return matchBuilder
+ */
+ public static MatchBuilder createSmacTcpPortWithFlagMatch(MatchBuilder matchBuilder, String attachedMac,
+ Integer tcpFlag, String tunnelID) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetMatch.setEthernetType(ethTypeBuilder.build());
+
+ EthernetSourceBuilder ethSrcBuilder = new EthernetSourceBuilder();
+ ethSrcBuilder.setAddress(new MacAddress(attachedMac));
+ ethernetMatch.setEthernetSource(ethSrcBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol(TCP_SHORT);
+ matchBuilder.setIpMatch(ipMatch.build());
+
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(tcpFlag);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+
+ TunnelBuilder tunnelBuilder = new TunnelBuilder();
+ tunnelBuilder.setTunnelId(new BigInteger(tunnelID));
+ matchBuilder.setTunnel(tunnelBuilder.build());
+
+ return matchBuilder;
+ }
+
+ /**
+ * Create smac ip tcp syn match.
+ *
+ * @param matchBuilder the match builder
+ * @param dMacAddr the d mac addr
+ * @param mask the mask
+ * @param ipPrefix the ip prefix
+ * @return MatchBuilder containing the metadata match values
+ */
+ public static MatchBuilder createSmacIpTcpSynMatch(MatchBuilder matchBuilder, MacAddress dMacAddr,
+ MacAddress mask, Ipv4Prefix ipPrefix) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetSourceBuilder ethSrcBuilder = new EthernetSourceBuilder();
+ ethSrcBuilder.setAddress(new MacAddress(dMacAddr));
+ if (mask != null) {
+ ethSrcBuilder.setMask(mask);
+ }
+ ethernetMatch.setEthernetSource(ethSrcBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+ // Ethertype match
+ EthernetMatchBuilder ethernetType = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetType.setEthernetType(ethTypeBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetType.build());
+ if (ipPrefix != null) {
+ Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
+ ipv4match.setIpv4Destination(ipPrefix);
+ matchBuilder.setLayer3Match(ipv4match.build());
+ }
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol(TCP_SHORT);
+ matchBuilder.setIpMatch(ipMatch.build());
+ // TCP Flag Match
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(TCP_SYN);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+
+ return matchBuilder;
+ }
+
+ /**
+ * Create smac tcp syn.
+ *
+ * @param matchBuilder the match builder
+ * @param attachedMac the attached mac
+ * @param tcpPort the tcp port
+ * @param tcpFlag the tcp flag
+ * @param tunnelID the tunnel iD
+ * @return the match builder
+ */
+ public static MatchBuilder createSmacTcpSyn(MatchBuilder matchBuilder,
+ String attachedMac, PortNumber tcpPort, Integer tcpFlag, String tunnelID) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetMatch.setEthernetType(ethTypeBuilder.build());
+
+ EthernetSourceBuilder ethSrcBuilder = new EthernetSourceBuilder();
+ ethSrcBuilder.setAddress(new MacAddress(attachedMac));
+ ethernetMatch.setEthernetSource(ethSrcBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol((short) 6);
+ matchBuilder.setIpMatch(ipMatch.build());
+
+ // TCP Port Match
+ PortNumber dstPort = new PortNumber(tcpPort);
+ TcpMatchBuilder tcpMatch = new TcpMatchBuilder();
+ tcpMatch.setTcpDestinationPort(dstPort);
+ matchBuilder.setLayer4Match(tcpMatch.build());
+
+
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(tcpFlag);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+
+ TunnelBuilder tunnelBuilder = new TunnelBuilder();
+ tunnelBuilder.setTunnelId(new BigInteger(tunnelID));
+ matchBuilder.setTunnel(tunnelBuilder.build());
+
+ return matchBuilder;
+ }
+
+ /**
+ * @return MatchBuilder containing the metadata match values
+ */
+ public static MatchBuilder createMacSrcIpTcpSynMatch(MatchBuilder matchBuilder,
+ MacAddress dMacAddr, MacAddress mask, Ipv4Prefix ipPrefix) {
+
+ EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+ EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder();
+ ethDestinationBuilder.setAddress(new MacAddress(dMacAddr));
+ if (mask != null) {
+ ethDestinationBuilder.setMask(mask);
+ }
+ ethernetMatch.setEthernetDestination(ethDestinationBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetMatch.build());
+ // Ethertype match
+ EthernetMatchBuilder ethernetType = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0800L));
+ ethernetType.setEthernetType(ethTypeBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetType.build());
+ if (ipPrefix != null) {
+ Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
+ ipv4match.setIpv4Source(ipPrefix);
+ matchBuilder.setLayer3Match(ipv4match.build());
+ }
+ // TCP Protocol Match
+ IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
+ ipMatch.setIpProtocol(TCP_SHORT);
+ matchBuilder.setIpMatch(ipMatch.build());
+ // TCP Flag Match
+ TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder();
+ tcpFlagMatch.setTcpFlag(TCP_SYN);
+ matchBuilder.setTcpFlagMatch(tcpFlagMatch.build());
+
+ return matchBuilder;
+ }
+
public static class RegMatch {
final Class<? extends NxmNxReg> reg;
final Long value;