import javax.annotation.Nonnull;
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.clustering.CandidateAlreadyRegisteredException;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.HwvtepGlobalRemoveCommand;
import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.PhysicalSwitchRemoveCommand;
import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvoker;
import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
import org.opendaylight.ovsdb.schema.hardwarevtep.Global;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalSwitchAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ConnectionInfo;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoCloseable{
private Map<ConnectionInfo, HwvtepConnectionInstance> clients =
ConnectionInfo connectionInfo = HwvtepSouthboundMapper.suppressLocalIpPort(key);
return clients.get(connectionInfo);
}
+
public HwvtepConnectionInstance getConnectionInstance(Node node) {
Preconditions.checkNotNull(node);
HwvtepGlobalAugmentation hwvtepGlobal = node.getAugmentation(HwvtepGlobalAugmentation.class);
+ PhysicalSwitchAugmentation pSwitchNode = node.getAugmentation(PhysicalSwitchAugmentation.class);
if (hwvtepGlobal != null) {
return getConnectionInstance(hwvtepGlobal.getConnectionInfo());
} //TODO: We could get it from Managers also.
- else {
+ else if(pSwitchNode != null){
+ return getConnectionInstance(pSwitchNode);
+ } else {
LOG.warn("This is not a node that gives any hint how to find its OVSDB Manager: {}",node);
return null;
}
}
+ public HwvtepConnectionInstance getConnectionInstance(InstanceIdentifier<Node> nodePath) {
+ try {
+ ReadOnlyTransaction transaction = db.newReadOnlyTransaction();
+ CheckedFuture<Optional<Node>, ReadFailedException> nodeFuture = transaction.read(
+ LogicalDatastoreType.OPERATIONAL, nodePath);
+ transaction.close();
+ Optional<Node> optional = nodeFuture.get();
+ if (optional != null && optional.isPresent() && optional.get() instanceof Node) {
+ return this.getConnectionInstance(optional.get());
+ } else {
+ LOG.warn("Found non-topological node {} on path {}",optional);
+ return null;
+ }
+ } catch (Exception e) {
+ LOG.warn("Failed to get Hwvtep Node {}",nodePath, e);
+ return null;
+ }
+ }
+
+ private HwvtepConnectionInstance getConnectionInstance(HwvtepPhysicalSwitchAttributes pNode) {
+ Optional<HwvtepGlobalAugmentation> optional = HwvtepSouthboundUtil.getManagingNode(db, pNode);
+ if(optional.isPresent()) {
+ return getConnectionInstance(optional.get().getConnectionInfo());
+ } else {
+ return null;
+ }
+ }
+
private void removeConnectionInstance(ConnectionInfo key) {
ConnectionInfo connectionInfo = HwvtepSouthboundMapper.suppressLocalIpPort(key);
clients.remove(connectionInfo);
package org.opendaylight.ovsdb.hwvtepsouthbound;
+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.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalSwitchAttributes;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.CheckedFuture;
public class HwvtepSouthboundUtil {
}
return result;
}
+
+ public static Optional<HwvtepGlobalAugmentation> getManagingNode(DataBroker db,
+ HwvtepPhysicalSwitchAttributes pNode) {
+ Preconditions.checkNotNull(pNode);
+ Optional<HwvtepGlobalAugmentation> result = null;
+ HwvtepGlobalRef ref = pNode.getManagedBy();
+ if (ref != null && ref.getValue() != null) {
+ result = getManagingNode(db, ref);
+ } else {
+ LOG.warn("Cannot find client for PhysicalSwitch without a specified ManagedBy {}", pNode);
+ return Optional.absent();
+ }
+ if (!result.isPresent()) {
+ LOG.warn("Failed to find managing node for PhysicalSwitch {}", pNode);
+ }
+ return result;
+ }
+
+ public static Optional<HwvtepGlobalAugmentation> getManagingNode(DataBroker db,
+ HwvtepLogicalSwitchAttributes lNode) {
+ Preconditions.checkNotNull(lNode);
+ Optional<HwvtepGlobalAugmentation> result = null;
+ // TODO: Add managed-by to hwvtep-logical-switch-attributes in
+ // hwvtep.yang
+ /*
+ * HwvtepGlobalRef ref = lNode.getManagedBy(); if (ref != null &&
+ * ref.getValue() != null) { result = getManagingNode(db, ref); } else {
+ * LOG.warn(
+ * "Cannot find client for LogicalSwitch without a specified ManagedBy {}"
+ * , pNode); return Optional.absent(); } if(!result.isPresent()) {
+ * LOG.warn("Failed to find managing node for PhysicalSwitch {}",
+ * pNode); } return result;
+ */
+ return Optional.absent(); // TODO: Delete this once yang is updated
+ }
+
+ private static Optional<HwvtepGlobalAugmentation> getManagingNode(DataBroker db, HwvtepGlobalRef ref) {
+ try {
+ ReadOnlyTransaction transaction = db.newReadOnlyTransaction();
+ @SuppressWarnings("unchecked")
+ // Note: erasure makes this safe in combination with the typecheck
+ // below
+ InstanceIdentifier<Node> path = (InstanceIdentifier<Node>) ref.getValue();
+
+ CheckedFuture<Optional<Node>, ReadFailedException> nf =
+ transaction.read(LogicalDatastoreType.OPERATIONAL, path);
+ transaction.close();
+ Optional<Node> optional = nf.get();
+ if (optional != null && optional.isPresent()) {
+ HwvtepGlobalAugmentation hwvtepNode = null;
+ Node node = optional.get();
+ if (node instanceof HwvtepGlobalAugmentation) {
+ hwvtepNode = (HwvtepGlobalAugmentation) node;
+ } else if (node != null) {
+ hwvtepNode = node.getAugmentation(HwvtepGlobalAugmentation.class);
+ }
+ if (hwvtepNode != null) {
+ return Optional.of(hwvtepNode);
+ } else {
+ LOG.warn("Hwvtep switch claims to be managed by {} but " + "that HwvtepNode does not exist",
+ ref.getValue());
+ return Optional.absent();
+ }
+ } else {
+ LOG.warn("Mysteriously got back a thing which is *not* a topology Node: {}", optional);
+ return Optional.absent();
+ }
+ } catch (Exception e) {
+ LOG.warn("Failed to get HwvtepNode {}", ref, e);
+ return Optional.absent();
+ }
+ }
+
}
super(message, cause);
}
- public static String createMessage(Version currentVersion, Version requiredVersion) {
- String message =
- "The schema version used to access this Table/Column does not match the required version.\n"
- + "Current Version: " + currentVersion.toString() + "\n";
-
- if (currentVersion.compareTo(requiredVersion) > 1) {
- message += "Removed in Version: " + requiredVersion.toString();
-
- } else {
- message += "Added in Version: " + requiredVersion.toString();
-
- }
-
- return message;
+ public SchemaVersionMismatchException(Version schemaVersion, Version fromVersion, Version untilVersion) {
+ this("The schema version used to access the table/column (" + schemaVersion + ") does not match the required " +
+ "version (from " + fromVersion + " to " + untilVersion + ")");
}
}
}
private static void checkVersion(Version schemaVersion, Version fromVersion, Version untilVersion) {
- if (!fromVersion.equals(Version.NULL) && schemaVersion.compareTo(fromVersion) < 0) {
- String message = SchemaVersionMismatchException.createMessage(schemaVersion, fromVersion);
- throw new SchemaVersionMismatchException(message);
- }
- if (!untilVersion.equals(Version.NULL) && schemaVersion.compareTo(untilVersion) > 0) {
- String message = SchemaVersionMismatchException.createMessage(schemaVersion, untilVersion);
- throw new SchemaVersionMismatchException(message);
+ if ((!fromVersion.equals(Version.NULL) && schemaVersion.compareTo(fromVersion) < 0) || (!untilVersion.equals(
+ Version.NULL) && schemaVersion.compareTo(untilVersion) > 0)) {
+ throw new SchemaVersionMismatchException(schemaVersion, fromVersion, untilVersion);
}
}
bridgeDelete(testBridgeUuid);
}
- @Test
+ @Test(expected = SchemaVersionMismatchException.class)
public void testFlowSampleCollectorSetTableNotSupported () {
// Don't run this test if the table is not supported
assumeTrue(schemaVersion.compareTo(flowSampleCollectorSetFromVersion) < 0);
- boolean isExceptionRaised = false;
- try {
- getClient().createTypedRowWrapper(FlowSampleCollectorSet.class);
- } catch (SchemaVersionMismatchException e) {
- isExceptionRaised = true;
- }
- assertTrue(isExceptionRaised);
+ getClient().createTypedRowWrapper(FlowSampleCollectorSet.class);
}
public void flowSampleCollectorSetInsert () throws ExecutionException, InterruptedException {
bridgeDelete(testBridgeUuid);
}
- @Test
+ @Test(expected = SchemaVersionMismatchException.class)
public void testFlowTableTableNotSupported () {
// Don't run this test if the table is not supported
assumeTrue(schemaVersion.compareTo(flowTableFromVersion) < 0);
- boolean isExceptionRaised = false;
- try {
- getClient().createTypedRowWrapper(FlowTable.class);
- } catch (SchemaVersionMismatchException e) {
- isExceptionRaised = true;
- }
- assertTrue(isExceptionRaised);
+ getClient().createTypedRowWrapper(FlowTable.class);
}
public void flowTableInsert () throws ExecutionException, InterruptedException {
bridgeDelete(testBridgeUuid);
}
- @Test
+ @Test(expected = SchemaVersionMismatchException.class)
public void testIpfixTableNotSupported () {
// Don't run this test if the table is not supported
assumeTrue(schemaVersion.compareTo(ipfixFromVersion) < 0);
- boolean isExceptionRaised = false;
- try {
- getClient().createTypedRowWrapper(IPFIX.class);
- } catch (SchemaVersionMismatchException e) {
- isExceptionRaised = true;
- }
- assertTrue(isExceptionRaised);
+ getClient().createTypedRowWrapper(IPFIX.class);
}
public void ipfixInsert () throws ExecutionException, InterruptedException {
* http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
*
*/
+
+ if (portSecurityRule == null ||
+ portSecurityRule.getSecurityRuleEthertype() == null ||
+ portSecurityRule.getSecurityRuleDirection() == null) {
+ continue;
+ }
+
if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
&& portSecurityRule.getSecurityRuleDirection().equals("egress")) {
LOG.debug("programPortSecurityGroup: Acl Rule matching IPv4 and ingress is: {} ", portSecurityRule);
*
*/
+ if (portSecurityRule == null ||
+ portSecurityRule.getSecurityRuleEthertype() == null ||
+ portSecurityRule.getSecurityRuleDirection() == null) {
+ continue;
+ }
+
if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
&& "ingress".equals(portSecurityRule.getSecurityRuleDirection())) {
LOG.debug("programPortSecurityGroup: Rule matching IPv4 and ingress is: {} ", portSecurityRule);
verify(commitFuture, times(1)).get();
}
*/
+ /**
+ * Test method {@link EgressAclService#programPortSecurityGroup(java.lang.Long, java.lang.String,
+ * java.lang.String, long, org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup,
+ * java.lang.String, boolean)} when portSecurityRule is incomplete
+ */
+ @Test
+ public void testProgramPortSecurityGroupWithIncompleteRule() throws Exception {
+ NeutronSecurityRule portSecurityRule1 = mock(NeutronSecurityRule.class);
+ when(portSecurityRule1.getSecurityRuleEthertype()).thenReturn("IPv4");
+ when(portSecurityRule1.getSecurityRuleDirection()).thenReturn("not_egress"); // other direction
+
+ NeutronSecurityRule portSecurityRule2 = mock(NeutronSecurityRule.class);
+ when(portSecurityRule2.getSecurityRuleEthertype()).thenReturn(null);
+ when(portSecurityRule2.getSecurityRuleDirection()).thenReturn("egress");
+
+ NeutronSecurityRule portSecurityRule3 = mock(NeutronSecurityRule.class);
+ when(portSecurityRule3.getSecurityRuleEthertype()).thenReturn("IPv4");
+ when(portSecurityRule3.getSecurityRuleDirection()).thenReturn(null);
+
+ NeutronSecurityRule portSecurityRule4 = mock(NeutronSecurityRule.class);
+ when(portSecurityRule4.getSecurityRuleEthertype()).thenReturn(null);
+ when(portSecurityRule4.getSecurityRuleDirection()).thenReturn(null);
+
+ List<NeutronSecurityRule> portSecurityList = new ArrayList<>();
+ portSecurityList.add(null);
+ portSecurityList.add(portSecurityRule1);
+ portSecurityList.add(portSecurityRule2);
+ portSecurityList.add(portSecurityRule3);
+ portSecurityList.add(portSecurityRule4);
+
+ NeutronSecurityGroup localSecurityGroup = mock(NeutronSecurityGroup.class);
+ when(localSecurityGroup.getSecurityRules()).thenReturn(portSecurityList);
+
+ egressAclServiceSpy.programPortSecurityGroup(DP_ID_LONG, SEGMENT_ID, MAC_ADDRESS, LOCAL_PORT,
+ localSecurityGroup, PORT_UUID, true);
+ }
+
/**
* Test method {@link EgressAclService#egressACLDefaultTcpDrop(Long, String, String, int, boolean)}
*/
verify(commitFuture, times(1)).get();
}
*/
+ /**
+ * Test method {@link EgressAclService#programPortSecurityGroup(java.lang.Long, java.lang.String,
+ * java.lang.String, long, org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup,
+ * java.lang.String, boolean)} when portSecurityRule is incomplete
+ */
+ @Test
+ public void testProgramPortSecurityGroupWithIncompleteRule() throws Exception {
+ NeutronSecurityRule portSecurityRule1 = mock(NeutronSecurityRule.class);
+ when(portSecurityRule1.getSecurityRuleEthertype()).thenReturn("IPv4");
+ when(portSecurityRule1.getSecurityRuleDirection()).thenReturn("not_ingress"); // other direction
+
+ NeutronSecurityRule portSecurityRule2 = mock(NeutronSecurityRule.class);
+ when(portSecurityRule2.getSecurityRuleEthertype()).thenReturn(null);
+ when(portSecurityRule2.getSecurityRuleDirection()).thenReturn("ingress");
+
+ NeutronSecurityRule portSecurityRule3 = mock(NeutronSecurityRule.class);
+ when(portSecurityRule3.getSecurityRuleEthertype()).thenReturn("IPv4");
+ when(portSecurityRule3.getSecurityRuleDirection()).thenReturn(null);
+
+ NeutronSecurityRule portSecurityRule4 = mock(NeutronSecurityRule.class);
+ when(portSecurityRule4.getSecurityRuleEthertype()).thenReturn(null);
+ when(portSecurityRule4.getSecurityRuleDirection()).thenReturn(null);
+
+ List<NeutronSecurityRule> portSecurityList = new ArrayList<>();
+ portSecurityList.add(null);
+ portSecurityList.add(portSecurityRule1);
+ portSecurityList.add(portSecurityRule2);
+ portSecurityList.add(portSecurityRule3);
+ portSecurityList.add(portSecurityRule4);
+
+ NeutronSecurityGroup localSecurityGroup = mock(NeutronSecurityGroup.class);
+ when(localSecurityGroup.getSecurityRules()).thenReturn(portSecurityList);
+
+ ingressAclServiceSpy.programPortSecurityGroup(
+ Long.valueOf(1554), "2", MAC_ADDRESS, 124, localSecurityGroup, PORT_UUID, false);
+ }
+
/**
* Test IPv4 add test case.
*/
<Export-Package>
org.opendaylight.yang.gen.v1.*,
org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105,
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.*,
org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105,
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.*,
org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105,
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.*
</Export-Package>
</instructions>
</configuration>
description "Initial revision of netvirt extensions to ietf-acl model";
}
- // TODO: Add choice for Neutron and add fields there instead of at the root of matches
//augment "/ietf-acl:access-lists/ietf-acl:access-list/ietf-acl:access-list-entries/ietf-acl:access-list-entry/ietf-acl:matches" {
augment "/ietf-acl:access-lists/ietf-acl:acl/ietf-acl:access-list-entries/ietf-acl:ace/ietf-acl:matches" {
description "Neutron network uuid";
}
}
- // TODO: Add choice for Neutron and add fields there instead of at the root of matches
augment "/ietf-acl:access-lists/ietf-acl:acl/ietf-acl:access-list-entries/ietf-acl:ace/ietf-acl:actions" {
- description "Redirect traffic to SFC identified by SFC Path ID";
+ description "Redirect traffic to SFC identified by either SFC, SFP or RSP";
ext:augment-identifier "redirect-to-sfc";
- leaf redirect-sfc {
+ leaf sfc-name {
+ type string;
+ }
+ leaf sfp-name {
+ type string;
+ }
+ leaf rsp-name {
type string;
}
}
<artifactId>openstack.net-virt-providers</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>southbound-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>southbound-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>utils.mdsal-utils</artifactId>
<version>${sonar-jacoco-listeners.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>iana-if-type-2014-05-08</artifactId>
+ <version>2014.05.08.8-SNAPSHOT</version>
+ </dependency>
</dependencies>
<build>
</instructions>
</configuration>
</plugin>
- <plugin>
+ <!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
- <!--<configuration>
+ <configuration>
<propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
- </configuration>-->
- </plugin>
+ </configuration>
+ </plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
package org.opendaylight.ovsdb.openstack.netvirt.sfc;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services.SfcClassifierService;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.Acl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.Bridges;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
+import org.osgi.framework.ServiceReference;
/**
* Open vSwitch OpenFlow 1.3 Networking Provider for Netvirt SFC
void addClassifierRules(Acl acl);
void removeClassifierRules(Acl acl);
+
+ void setSfcClassifierService(ISfcClassifierService sfcClassifierService);
+ public void setDependencies(ServiceReference serviceReference);
}
--- /dev/null
+/*
+ * Copyright © 2015 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.sfc;
+
+import java.net.InetAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+
+public interface ISfcClassifierService {
+ void programIngressClassifier(long dataPathId, String ruleName, Matches matches,
+ NshUtils nshHeader, long vxGpeOfPort, boolean write);
+
+ void programSfcTable(long dataPathId, long vxGpeOfPort, short goToTableId, boolean write);
+
+ void programEgressClassifier1(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
+ int tunnelOfPort, int tunnelId, short gotoTableId, boolean write);
+
+ void programEgressClassifier2(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
+ int tunnelOfPort, int tunnelId, boolean write);
+
+ void program_sfEgress(long dataPathId, int dstPort, boolean write);
+
+ void program_sfIngress(long dataPathId, int dstPort, long sfOfPort,
+ String ipAddress, String sfDplName, boolean write);
+
+ void programStaticArpEntry(long dataPathId, long ofPort, String macAddressStr,
+ String ipAddress, boolean write);
+}
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.NetvirtSfcStandaloneOF13Provider;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.services.SfcClassifierService;
-import org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services.NetvirtSfcWorkaroundOF13Provider;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.NetvirtSfcWorkaroundOF13Provider;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
MdsalUtils mdsalUtils = new MdsalUtils(dataBroker);
SfcUtils sfcUtils = new SfcUtils(mdsalUtils);
+
// Allocate provider based on config
INetvirtSfcOF13Provider provider;
if (of13Provider.equals("standalone")) {
aclListener = new NetvirtSfcAclListener(provider, dataBroker);
classifierListener = new NetvirtSfcClassifierListener(provider, dataBroker);
- addToPipeline();
+ addToPipeline(provider);
+ provider.setDependencies(null);
}
@Override
classifierListener.close();
}
- private void addToPipeline() {
- SfcClassifierService sfcClassifierService = new SfcClassifierService();
- registerService(bundleContext, SfcClassifierService.class.getName(),
- sfcClassifierService, Service.SFC_CLASSIFIER);
- sfcClassifierService.setDependencies(bundleContext, null);
+ private void addToPipeline(INetvirtSfcOF13Provider provider) {
+ if (provider instanceof NetvirtSfcStandaloneOF13Provider) {
+ SfcClassifierService sfcClassifierService =
+ new org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.services.SfcClassifierService();
+ registerService(bundleContext, ISfcClassifierService.class.getName(),
+ sfcClassifierService, Service.SFC_CLASSIFIER);
+ sfcClassifierService.setDependencies(bundleContext, null);
+ } else {
+ org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services.SfcClassifierService sfcClassifierService =
+ new org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services.SfcClassifierService();
+ registerService(bundleContext, ISfcClassifierService.class.getName(),
+ sfcClassifierService, Service.SFC_CLASSIFIER);
+ sfcClassifierService.setDependencies(bundleContext, null);
}
+ //provider.setSfcClassifierService(sfcClassifierService);
+ }
+
private ServiceRegistration<?> registerService(BundleContext bundleContext, String[] interfaces,
Dictionary<String, Object> properties, Object impl) {
ServiceRegistration<?> serviceRegistration = bundleContext.registerService(interfaces, impl, properties);
properties.put(AbstractServiceInstance.SERVICE_PROPERTY, serviceProperty);
properties.put(Constants.PROVIDER_NAME_PROPERTY, OF13Provider.NAME);
return registerService(bundleContext,
- new String[] {AbstractServiceInstance.class.getName(),
- interfaceClassName}, properties, impl);
+ new String[] {AbstractServiceInstance.class.getName(),interfaceClassName},
+ properties, impl);
}
}
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceFunctionAPI;
import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePaths;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Ip;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class SfcUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(SfcUtils.class);
private MdsalUtils mdsalUtils;
public SfcUtils(MdsalUtils mdsalUtils) {
.child(RenderedServicePath.class, new RenderedServicePathKey(new RspName(rspName))).build();
}
+ public InstanceIdentifier<ServiceFunction> getSfId(String sfName) {
+ return InstanceIdentifier.builder(ServiceFunctions.class)
+ .child(ServiceFunction.class, new ServiceFunctionKey(SfName.getDefaultInstance(sfName))).build();
+ }
+
+ public RenderedServicePath getRsp(String rspName) {
+ return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, getRspId(rspName));
+ }
+
public RenderedServicePath getRspforSfp(String sfpName) {
RenderedServicePath rspFound = null;
RenderedServicePaths rsps = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, this.getRspsId());
}
return sfpFound;
}
+
+ public IpAddress getSfIpAddress(String sfname) {
+ ServiceFunction serviceFunction =
+ SfcProviderServiceFunctionAPI.readServiceFunction(SfName.getDefaultInstance(sfname));
+
+ if (serviceFunction == null) {
+ LOG.info("Failed to read ServiceFunction: {}", sfname);
+ return null;
+ }
+
+ return getSfIpAddress(serviceFunction);
+ }
+
+ public IpAddress getSfIpAddress(ServiceFunction serviceFunction) {
+ if (serviceFunction == null) {
+ LOG.info("getSfIp: Servicefunction is null");
+ return null;
+ }
+
+ Ip ipLocator = (Ip) serviceFunction.getSfDataPlaneLocator().get(0).getLocatorType();
+ return ipLocator.getIp();
+ }
+
+ public PortNumber getSfPort(ServiceFunction serviceFunction) {
+ if (serviceFunction == null) {
+ LOG.info("getSfIp: Servicefunction is null");
+ return null;
+ }
+
+ Ip ipLocator = (Ip) serviceFunction.getSfDataPlaneLocator().get(0).getLocatorType();
+ return ipLocator.getPort();
+ }
+
+ public Ip getSfIp(ServiceFunction serviceFunction) {
+ if (serviceFunction == null) {
+ LOG.info("getSfIp: Servicefunction is null");
+ return null;
+ }
+
+ return (Ip)serviceFunction.getSfDataPlaneLocator().get(0).getLocatorType();
+ }
+
+ public String getSfDplName(ServiceFunction serviceFunction) {
+ String sfDplName = null;
+ if (serviceFunction == null) {
+ LOG.warn("getSfDplName: Servicefunction is null");
+ return null;
+ }
+
+ sfDplName = serviceFunction.getSfDataPlaneLocator().get(0).getName().getValue();
+ return sfDplName;
+ }
+
+ public Ip getSffIp(ServiceFunctionForwarder serviceFunctionForwarder) {
+ if (serviceFunctionForwarder == null) {
+ LOG.info("getSfIp: ServicefunctionForwarder is null");
+ return null;
+ }
+
+ return (Ip)serviceFunctionForwarder.getSffDataPlaneLocator().get(0).getDataPlaneLocator().getLocatorType();
+ }
}
import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.INetvirtSfcOF13Provider;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.ISfcClassifierService;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.NshUtils;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
public NetvirtSfcStandaloneOF13Provider(final DataBroker dataBroker) {
Preconditions.checkNotNull(dataBroker, "Input dataBroker cannot be NULL!");
mdsalUtils = new MdsalUtils(dataBroker);
- this.setDependencies(null);
+ //this.setDependencies(null);
sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
}
}
}
+ @Override
+ public void setSfcClassifierService(ISfcClassifierService sfcClassifierService) {
+
+ }
+
@Override
public void addClassifierRules(Bridge bridge, Acl acl) {
return;
}
- RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
- LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
- if (sfcRedirect == null) {
- LOG.warn("processAClEntry: sfcRedirect is null");
- return;
- }
-
- String sfcName = sfcRedirect.getRedirectSfc();
- LOG.debug("Processing Redirect to SFC = {}", sfcRedirect.getRedirectSfc());
- ServiceFunctionPath sfp = getSfp(sfcName);
- if (sfp == null || sfp.getName() == null) {
- LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
- return;
- }
-
- LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcRedirect.getRedirectSfc(), sfp);
- // If RSP doesn't exist, create an RSP.
- String sfpName = sfp.getName().getValue();
- RenderedServicePath rsp = getRspforSfp(sfpName);
- String rspName = sfp.getName().getValue() + "_rsp";
+ RenderedServicePath rsp = getRenderedServicePath(entry);
if (rsp == null) {
- LOG.info("No configured RSP corresponding to SFP = {}, Creating new RSP = {}", sfpName, rspName);
- CreateRenderedPathInput rspInput = new CreateRenderedPathInputBuilder()
- .setParentServiceFunctionPath(sfpName)
- .setName(rspName)
- .setSymmetric(sfp.isSymmetric())
- .build();
- rsp = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, rspInput);
- if (rsp == null) {
- LOG.warn("failed to add RSP");
- return;
- }
-
- // If SFP is symmetric, create RSP in the reverse direction.
- if (sfp.isSymmetric()) {
- LOG.info("SFP = {} is symmetric, installing RSP in the reverse direction!!", sfpName);
- String rspNameRev = rspName + "-Reverse";
- RenderedServicePath rspReverse = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
- this.getRspId(rspNameRev));
- if (rspReverse == null) {
- rspReverse = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
- if (rspReverse == null) {
- LOG.warn("failed to add reverse RSP");
- return;
- }
- }
- }
+ LOG.warn("Failed to get renderedServicePatch for entry: {}", entry);
+ return;
}
LOG.info("processAclEntry: RSP: {}", rsp);
List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
if (pathHopList.isEmpty()) {
- LOG.warn("Service Path = {} has empty hops!!", sfpName);
+ LOG.warn("Service Path = {} has empty hops!!", rsp.getName());
return;
}
// Find the first Hop within an RSP.
// The classifier flow needs to send all matched traffic to this first hop SFF.
RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
- .readRenderedServicePathFirstHop(new RspName(rspName));
+ .readRenderedServicePathFirstHop(new RspName(rsp.getName()));
LOG.debug("First Hop IPAddress = {}, Port = {}", firstRspHop.getIp().getIpv4Address().getValue(),
- firstRspHop.getPort().getValue().intValue());
+ firstRspHop.getPort().getValue());
NshUtils nshHeader = new NshUtils();
// C1 is the normal overlay dest ip and c2 is the vnid
}
}
+ private RenderedServicePath getRenderedServicePath (Ace entry) {
+ RenderedServicePath rsp = null;
+ RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
+ LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
+ if (sfcRedirect == null) {
+ LOG.warn("processAClEntry: sfcRedirect is null");
+ return null;
+ }
+
+ if (sfcRedirect.getRspName() != null) {
+ rsp = getRenderedServicePathFromRsp(sfcRedirect.getRspName());
+ } else if (sfcRedirect.getSfpName() != null) {
+ LOG.warn("getRenderedServicePath: sfp not handled yet");
+ } else {
+ rsp = getRenderedServicePathFromSfc(entry);
+ }
+ LOG.info("getRenderedServicePath: rsp: {}", rsp);
+ return rsp;
+ }
+
+ private RenderedServicePath getRenderedServicePathFromRsp(String rspName) {
+ return null;//getRsp(rspName);
+ }
+
+ private RenderedServicePath getRenderedServicePathFromSfc (Ace entry) {
+ RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
+ LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
+ if (sfcRedirect == null) {
+ LOG.warn("processAClEntry: sfcRedirect is null");
+ return null;
+ }
+
+ String sfcName = sfcRedirect.getSfcName();
+ ServiceFunctionPath sfp = getSfp(sfcName);
+ if (sfp == null || sfp.getName() == null) {
+ LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
+ return null;
+ }
+
+ LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcName, sfp);
+ // If RSP doesn't exist, create an RSP.
+ String sfpName = sfp.getName().getValue();
+ RenderedServicePath rsp = getRspforSfp(sfpName);
+ String rspName = sfp.getName().getValue() + "_rsp";
+ if (rsp == null) {
+ LOG.info("No configured RSP corresponding to SFP = {}, Creating new RSP = {}", sfpName, rspName);
+ CreateRenderedPathInput rspInput = new CreateRenderedPathInputBuilder()
+ .setParentServiceFunctionPath(sfpName)
+ .setName(rspName)
+ .setSymmetric(sfp.isSymmetric())
+ .build();
+ rsp = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, rspInput);
+ if (rsp == null) {
+ LOG.warn("failed to add RSP");
+ return null;
+ }
+
+ // If SFP is symmetric, create RSP in the reverse direction.
+ if (sfp.isSymmetric()) {
+ LOG.info("SFP = {} is symmetric, installing RSP in the reverse direction!!", sfpName);
+ String rspNameRev = rspName + "-Reverse";
+ RenderedServicePath rspReverse = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
+ getRspId(rspNameRev));
+ if (rspReverse == null) {
+ rspReverse = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
+ if (rspReverse == null) {
+ LOG.warn("failed to add reverse RSP");
+ return null;
+ }
+ }
+ }
+ }
+ return rsp;
+ }
+
private void handleLocalEgressPort(long dataPathId, String s, long localOfPort, short writeTable,
short gotoTable, boolean write) {
sfcClassifier.programLocalInPort(dpidLong, segmentationId, inPort, writeTable, goToTableId, matches, write);
}
- private void setDependencies(ServiceReference serviceReference) {
+ @Override
+ public void setDependencies(ServiceReference serviceReference) {
nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
}
import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.ISfcClassifierService;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.NshUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class SfcClassifierService extends AbstractServiceInstance implements ConfigInterface {
+public class SfcClassifierService extends AbstractServiceInstance implements ConfigInterface, ISfcClassifierService {
private static final Logger LOG = LoggerFactory.getLogger(SfcClassifierService.class);
public SfcClassifierService(Service service) {
@Override
public void setDependencies(Object impl) {}
+
+ @Override
+ public void programIngressClassifier(long dataPathId, String ruleName, Matches matches, NshUtils nshHeader, long vxGpeOfPort, boolean write) {
+
+ }
+
+ @Override
+ public void programSfcTable(long dataPathId, long vxGpeOfPort, short goToTableId, boolean write) {
+
+ }
+
+ @Override
+ public void programEgressClassifier1(long dataPathId, long vxGpeOfPort, long nsp, short nsi, int tunnelOfPort, int tunnelId, short gotoTableId, boolean write) {
+
+ }
+
+ @Override
+ public void programEgressClassifier2(long dataPathId, long vxGpeOfPort, long nsp, short nsi, int tunnelOfPort, int tunnelId, boolean write) {
+
+ }
+
+ @Override
+ public void program_sfEgress(long dataPathId, int dstPort, boolean write) {
+
+ }
+
+ @Override
+ public void program_sfIngress(long dataPathId, int dstPort, long sfOfPort, String ipAddress, String sfDplName, boolean write) {
+
+ }
+
+ @Override
+ public void programStaticArpEntry(long dataPathId, long ofPort, String macAddressStr, String ipAddress, boolean write) {
+
+ }
}
--- /dev/null
+/*
+ * Copyright © 2015 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround;
+
+import com.google.common.base.Preconditions;
+import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbTables;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.INetvirtSfcOF13Provider;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.ISfcClassifierService;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.NshUtils;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.SfcUtils;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
+import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceFunctionAPI;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Ip;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.path.first.hop.info.RenderedServicePathFirstHop;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.Classifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.Bridges;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider {
+ private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcWorkaroundOF13Provider.class);
+ private volatile NodeCacheManager nodeCacheManager;
+ private volatile Southbound southbound;
+ private volatile ISfcClassifierService sfcClassifierService;
+ private static final short SFC_TABLE = 150;
+ private static final int GPE_PORT = 6633;
+ private static final String NETWORK_TYPE_VXLAN = "vxlan";
+ private MdsalUtils mdsalUtils;
+ private SfcUtils sfcUtils;
+ private static final String VXGPE = "vxgpe";
+ private static final String TUNNEL_DST = "192.168.120.31";
+ private static final String TUNNEL_VNID = "10";
+ public static final String TUNNEL_ENDPOINT_KEY = "local_ip";
+
+ public NetvirtSfcWorkaroundOF13Provider(final DataBroker dataBroker, MdsalUtils mdsalUtils, SfcUtils sfcUtils) {
+ Preconditions.checkNotNull(dataBroker, "Input dataBroker cannot be NULL!");
+ Preconditions.checkNotNull(mdsalUtils, "Input mdsalUtils cannot be NULL!");
+ Preconditions.checkNotNull(sfcUtils, "Input sfcUtils cannot be NULL!");
+
+ this.mdsalUtils = mdsalUtils;
+ this.sfcUtils = sfcUtils;
+ //this.setDependencies(null);
+ }
+
+ public void setSfcClassifierService(ISfcClassifierService sfcClassifierService) {
+ this.sfcClassifierService = sfcClassifierService;
+ }
+
+ @Override
+ public void addClassifierRules(Bridge bridge, Acl acl) {
+
+ }
+
+ @Override
+ public void addClassifierRules(Bridges bridges, Acl acl) {
+ Preconditions.checkNotNull(bridges, "Input bridges cannot be NULL!");
+ Preconditions.checkNotNull(acl, "Input acl cannot be NULL!");
+ }
+
+ @Override
+ public void removeClassifierRules(Sff sff, Acl acl) {
+
+ }
+
+ @Override
+ public void addClassifierRules(Acl acl) {
+ String aclName = acl.getAclName();
+ Classifiers classifiers = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, sfcUtils.getClassifierIid());
+ if (classifiers == null) {
+ LOG.debug("addClassifierRules: No Classifiers found");
+ return;
+ }
+
+ LOG.debug("addClassifierRules: Classifiers: {}", classifiers);
+ for (Classifier classifier : classifiers.getClassifier()) {
+ if (classifier.getAcl().equals(aclName)) {
+ for (Ace ace : acl.getAccessListEntries().getAce()) {
+ processAclEntry(ace);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void removeClassifierRules(Acl acl) {
+
+ }
+
+ private void processAclEntry(Ace entry) {
+ Matches matches = entry.getMatches();
+ Preconditions.checkNotNull(matches, "Input bridges cannot be NULL!");
+
+ RenderedServicePath rsp = getRenderedServicePath(entry);
+ if (rsp == null) {
+ LOG.warn("Failed to get renderedServicePatch for entry: {}", entry);
+ return;
+ }
+
+ handleRenderedServicePath2(rsp, entry);
+ }
+
+ private void handleRenderedServicePath(RenderedServicePath rsp, Ace entry) {
+ LOG.info("handleRenderedServicePath: RSP: {}", rsp);
+
+ Matches matches = entry.getMatches();
+ if (matches == null) {
+ LOG.warn("processAclEntry: matches not found");
+ return;
+ }
+
+ List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
+ if (pathHopList.isEmpty()) {
+ LOG.warn("handleRenderedServicePath: RSP {} has empty hops!!", rsp.getName());
+ return;
+ }
+ LOG.info("handleRenderedServicePath: pathHopList: {}", pathHopList);
+
+ final List<Node> bridgeNodes = nodeCacheManager.getBridgeNodes();
+ if (bridgeNodes == null || bridgeNodes.isEmpty()) {
+ LOG.warn("handleRenderedServicePath: There are no bridges to process");
+ return;
+ }
+ for (Node bridgeNode : bridgeNodes) {
+ OvsdbBridgeAugmentation ovsdbBridgeAugmentation = southbound.getBridge(bridgeNode, "br-int");
+ if (ovsdbBridgeAugmentation == null) {
+ continue;
+ }
+ long vxGpeOfPort = getOFPort(bridgeNode, VXGPE);
+ if (vxGpeOfPort == 0L) {
+ LOG.warn("programAclEntry: Could not identify tunnel port {} -> OF ({}) on {}",
+ VXGPE, vxGpeOfPort, bridgeNode);
+ continue;
+ }
+ long dataPathId = southbound.getDataPathId(bridgeNode);
+ if (dataPathId == 0L) {
+ LOG.warn("programAclEntry: Could not identify datapathId on {}", bridgeNode);
+ continue;
+ }
+
+ // Find the first Hop within an RSP.
+ // The classifier flow needs to send all matched traffic to this first hop SFF.
+ RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
+ .readRenderedServicePathFirstHop(rsp.getName());
+
+ LOG.info("handleRenderedServicePath: firstRspHop: {}", firstRspHop);
+ LOG.debug("handleRenderedServicePath: First Hop IPAddress = {}, Port = {}",
+ firstRspHop.getIp().getIpv4Address().getValue(),
+ firstRspHop.getPort().getValue());
+
+ NshUtils nshHeader = new NshUtils();
+ nshHeader.setNshMetaC1(NshUtils.convertIpAddressToLong(new Ipv4Address(TUNNEL_DST)));
+ nshHeader.setNshMetaC2(Long.parseLong(TUNNEL_VNID)); // get from register //get from
+ nshHeader.setNshNsp(rsp.getPathId());
+
+ RenderedServicePathHop firstHop = pathHopList.get(0);
+ RenderedServicePathHop lastHop = pathHopList.get(pathHopList.size()-1);
+ ServiceFunction serviceFunction =
+ SfcProviderServiceFunctionAPI.readServiceFunction(
+ SfName.getDefaultInstance(firstHop.getServiceFunctionName().getValue()));
+ if (serviceFunction == null) {
+ LOG.warn("programAclEntry: Could not identify ServiceFunction {} on {}",
+ firstHop.getServiceFunctionName().getValue(), bridgeNode);
+ continue;
+ }
+
+ nshHeader.setNshNsi(firstHop.getServiceIndex());
+ // workaround: bypass sff and got directly to sf
+ //nshHeader.setNshTunIpDst(firstRspHop.getIp().getIpv4Address());
+ IpAddress sfIpAddress = sfcUtils.getSfIpAddress(serviceFunction);
+ String sfDplName = sfcUtils.getSfDplName(serviceFunction);
+ //sfcUtils.getSfIp(firstHop.getServiceFunctionName().getValue());
+ nshHeader.setNshTunIpDst(sfIpAddress.getIpv4Address());
+ nshHeader.setNshTunUdpPort(firstRspHop.getPort());
+ LOG.debug("handleRenderedServicePath: NSH Header = {}", nshHeader);
+
+ sfcClassifierService.programIngressClassifier(dataPathId, entry.getRuleName(), matches,
+ nshHeader, vxGpeOfPort, true);
+
+ sfcClassifierService.program_sfEgress(dataPathId, GPE_PORT, true);
+ long sfOfPort = getSfPort(bridgeNode, sfDplName);
+
+ String sfMac = getMacFromExternalIds(bridgeNode, sfDplName);
+ String sfIpString = new String(sfIpAddress.getValue());
+ LOG.info("handleRenderedServicePath: sfDplName: {}, sfMac: {}, sfOfPort: {}, sfIpAddress: {}",
+ sfDplName, sfMac, sfOfPort, sfIpString);
+ if (sfMac != null) { // install if the sf is on this bridge, expand when using multiple bridges
+ sfcClassifierService.program_sfIngress(dataPathId, GPE_PORT, sfOfPort, sfIpString, sfDplName, true);
+ sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpString, true);
+ }
+
+ short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
+ sfcClassifierService.programEgressClassifier1(dataPathId, vxGpeOfPort, rsp.getPathId(),
+ lastServiceindex, (int)sfOfPort, 0, (short)0, true);
+ sfcClassifierService.programEgressClassifier2(dataPathId, vxGpeOfPort, rsp.getPathId(),
+ lastServiceindex, (int)sfOfPort, 0, true);
+
+ sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
+ }
+ }
+
+ private void handleRenderedServicePath2(RenderedServicePath rsp, Ace entry) {
+ LOG.info("handleRenderedServicePath: RSP: {}", rsp);
+
+ Matches matches = entry.getMatches();
+ if (matches == null) {
+ LOG.warn("processAclEntry: matches not found");
+ return;
+ }
+
+ List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
+ if (pathHopList.isEmpty()) {
+ LOG.warn("handleRenderedServicePath: RSP {} has empty hops!!", rsp.getName());
+ return;
+ }
+ LOG.info("handleRenderedServicePath: pathHopList: {}", pathHopList);
+
+ RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
+ .readRenderedServicePathFirstHop(rsp.getName());
+ LOG.info("handleRenderedServicePath: firstRspHop: {}", firstRspHop);
+
+ RenderedServicePathHop firstHop = pathHopList.get(0);
+ RenderedServicePathHop lastHop = pathHopList.get(pathHopList.size()-1);
+
+ final List<Node> bridgeNodes = nodeCacheManager.getBridgeNodes();
+ if (bridgeNodes == null || bridgeNodes.isEmpty()) {
+ LOG.warn("handleRenderedServicePath: There are no bridges to process");
+ return;
+ }
+ for (RenderedServicePathHop hop : pathHopList) {
+ for (Node bridgeNode : bridgeNodes) {
+ long vxGpeOfPort = getOFPort(bridgeNode, VXGPE);
+ if (vxGpeOfPort == 0L) {
+ LOG.warn("programAclEntry: Could not identify gpe vtep {} -> OF ({}) on {}",
+ VXGPE, vxGpeOfPort, bridgeNode);
+ continue;
+ }
+ long dataPathId = southbound.getDataPathId(bridgeNode);
+ if (dataPathId == 0L) {
+ LOG.warn("programAclEntry: Could not identify datapathId on {}", bridgeNode);
+ continue;
+ }
+
+ ServiceFunction serviceFunction =
+ SfcProviderServiceFunctionAPI.readServiceFunction(firstHop.getServiceFunctionName());
+ if (serviceFunction == null) {
+ LOG.warn("programAclEntry: Could not identify ServiceFunction {} on {}",
+ firstHop.getServiceFunctionName().getValue(), bridgeNode);
+ continue;
+ }
+ ServiceFunctionForwarder serviceFunctionForwarder =
+ SfcProviderServiceForwarderAPI
+ .readServiceFunctionForwarder(hop.getServiceFunctionForwarder());
+ if (serviceFunctionForwarder == null) {
+ LOG.warn("programAclEntry: Could not identify ServiceFunctionForwarder {} on {}",
+ firstHop.getServiceFunctionName().getValue(), bridgeNode);
+ continue;
+ }
+
+ handleSf(bridgeNode, serviceFunction);
+ handleSff(bridgeNode, serviceFunctionForwarder, serviceFunction, hop, firstHop, lastHop,
+ entry.getRuleName(), matches, vxGpeOfPort, rsp);
+ if (firstHop == lastHop) {
+ handleSff(bridgeNode, serviceFunctionForwarder, serviceFunction, hop, null, lastHop,
+ entry.getRuleName(), matches, vxGpeOfPort, rsp);
+ }
+ }
+ }
+ }
+
+ private void handleSff(Node bridgeNode, ServiceFunctionForwarder serviceFunctionForwarder,
+ ServiceFunction serviceFunction,
+ RenderedServicePathHop hop,
+ RenderedServicePathHop firstHop,
+ RenderedServicePathHop lastHop,
+ String ruleName, Matches matches,
+ long vxGpeOfPort, RenderedServicePath rsp) {
+ long dataPathId = southbound.getDataPathId(bridgeNode);
+
+ if (hop == firstHop) {
+ NshUtils nshHeader = new NshUtils();
+ nshHeader.setNshNsp(rsp.getPathId());
+ nshHeader.setNshNsi(firstHop.getServiceIndex());
+ if (isSffOnBridge(bridgeNode, serviceFunctionForwarder)) {
+ Ip ip = sfcUtils.getSfIp(serviceFunction);
+ nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
+ nshHeader.setNshTunUdpPort(ip.getPort());
+ } else {
+ Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
+ nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
+ nshHeader.setNshTunUdpPort(ip.getPort());
+ }
+ sfcClassifierService.programIngressClassifier(dataPathId, ruleName, matches,
+ nshHeader, vxGpeOfPort, true);
+ } else if (hop == lastHop) {
+ short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
+ String sfDplName = sfcUtils.getSfDplName(serviceFunction);
+ long sfOfPort = getSfPort(bridgeNode, sfDplName);
+ sfcClassifierService.programEgressClassifier1(dataPathId, vxGpeOfPort, rsp.getPathId(),
+ lastServiceindex, (int)sfOfPort, 0, (short)0, true);
+ sfcClassifierService.programEgressClassifier2(dataPathId, vxGpeOfPort, rsp.getPathId(),
+ lastServiceindex, (int)sfOfPort, 0, true);
+ } else {
+ // add typical sff flows
+ }
+
+ sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
+ }
+
+ void handleSf(Node bridgeNode, ServiceFunction serviceFunction) {
+ if (isSfOnBridge(bridgeNode, serviceFunction)) {
+ long dataPathId = southbound.getDataPathId(bridgeNode);
+ Ip ip = sfcUtils.getSfIp(serviceFunction);
+ String sfIpAddr = String.valueOf(ip.getIp().getValue());
+ int sfIpPort = ip.getPort().getValue(); //GPE_PORT
+ String sfDplName = sfcUtils.getSfDplName(serviceFunction);
+ long sfOfPort = getSfPort(bridgeNode, sfDplName);
+ String sfMac = getMacFromExternalIds(bridgeNode, sfDplName);
+ //should be sffdplport, but they should all be the same 6633/4790
+ sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, true);
+ sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplName, true);
+ sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpAddr, true);
+ }
+ }
+
+ private boolean isSffOnBridge(Node bridgeNode, ServiceFunctionForwarder serviceFunctionForwarder) {
+ String local_ip = "";
+ Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
+ Node ovsdbNode = southbound.readOvsdbNode(bridgeNode);
+ if (ovsdbNode != null) {
+ OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
+ if (ovsdbNodeAugmentation != null && ovsdbNodeAugmentation.getOpenvswitchOtherConfigs() != null) {
+ southbound.getOtherConfig(ovsdbNode, OvsdbTables.OPENVSWITCH, TUNNEL_ENDPOINT_KEY);
+ }
+
+ }
+ return local_ip.equals(String.valueOf(ip.getIp().getValue()));
+ }
+
+ private boolean isSfOnBridge(Node bridgeNode, ServiceFunction serviceFunction) {
+ String sfDplName = sfcUtils.getSfDplName(serviceFunction);
+ long sfOfPort = getSfPort(bridgeNode, sfDplName);
+ return sfOfPort != 0L;
+ }
+
+ private RenderedServicePath getRenderedServicePath (Ace entry) {
+ RenderedServicePath rsp = null;
+ RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
+ LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
+ if (sfcRedirect == null) {
+ LOG.warn("processAClEntry: sfcRedirect is null");
+ return null;
+ }
+
+ if (sfcRedirect.getRspName() != null) {
+ rsp = getRenderedServicePathFromRsp(sfcRedirect.getRspName());
+ } else if (sfcRedirect.getSfpName() != null) {
+ LOG.warn("getRenderedServicePath: sfp not handled yet");
+ } else {
+ rsp = getRenderedServicePathFromSfc(entry);
+ }
+ LOG.info("getRenderedServicePath: rsp: {}", rsp);
+ return rsp;
+ }
+
+ private RenderedServicePath getRenderedServicePathFromRsp(String rspName) {
+ return sfcUtils.getRsp(rspName);
+ }
+
+ private RenderedServicePath getRenderedServicePathFromSfc (Ace entry) {
+ RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
+ LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
+ if (sfcRedirect == null) {
+ LOG.warn("processAClEntry: sfcRedirect is null");
+ return null;
+ }
+
+ String sfcName = sfcRedirect.getSfcName();
+ ServiceFunctionPath sfp = sfcUtils.getSfp(sfcName);
+ if (sfp == null || sfp.getName() == null) {
+ LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
+ return null;
+ }
+
+ LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcName, sfp);
+ // If RSP doesn't exist, create an RSP.
+ String sfpName = sfp.getName().getValue();
+ RenderedServicePath rsp = sfcUtils.getRspforSfp(sfpName);
+ String rspName = sfp.getName().getValue() + "_rsp";
+ if (rsp == null) {
+ LOG.info("No configured RSP corresponding to SFP = {}, Creating new RSP = {}", sfpName, rspName);
+ CreateRenderedPathInput rspInput = new CreateRenderedPathInputBuilder()
+ .setParentServiceFunctionPath(sfpName)
+ .setName(rspName)
+ .setSymmetric(sfp.isSymmetric())
+ .build();
+ rsp = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, rspInput);
+ if (rsp == null) {
+ LOG.warn("failed to add RSP");
+ return null;
+ }
+
+ // If SFP is symmetric, create RSP in the reverse direction.
+ if (sfp.isSymmetric()) {
+ LOG.info("SFP = {} is symmetric, installing RSP in the reverse direction!!", sfpName);
+ String rspNameRev = rspName + "-Reverse";
+ RenderedServicePath rspReverse = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
+ sfcUtils.getRspId(rspNameRev));
+ if (rspReverse == null) {
+ rspReverse = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
+ if (rspReverse == null) {
+ LOG.warn("failed to add reverse RSP");
+ return null;
+ }
+ }
+ }
+ }
+ return rsp;
+ }
+
+ // loop through all ports looking for vxlan types, skip vxgpe, keep the rest
+ // first pass we only have two tunnels: one for normal vxlan and the other for gpe
+ // so just return the first non-gpe vxlan port
+ private long getTunnelOfPort(Node bridgeNode, String vxGpePortName) {
+ long port = 0L;
+ List<OvsdbTerminationPointAugmentation> ovsdbTerminationPointAugmentations =
+ southbound.getTerminationPointsOfBridge(bridgeNode);
+ if (!ovsdbTerminationPointAugmentations.isEmpty()) {
+ for (OvsdbTerminationPointAugmentation terminationPointAugmentation :
+ ovsdbTerminationPointAugmentations) {
+ if (terminationPointAugmentation.getInterfaceType() ==
+ SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP.get(NETWORK_TYPE_VXLAN)) {
+ if (!terminationPointAugmentation.getName().equals(vxGpePortName)) {
+ port = terminationPointAugmentation.getOfport();
+ break;
+ }
+ }
+ }
+ }
+ return port;
+ }
+
+ private long getSfPort(Node bridgeNode, String sfPortName) {
+ long port = 0L;
+ port = getOFPort(bridgeNode, sfPortName);
+ return port;
+ }
+
+ private long getOFPort(Node bridgeNode, String portName) {
+ long ofPort = 0L;
+ OvsdbTerminationPointAugmentation port =
+ southbound.extractTerminationPointAugmentation(bridgeNode, portName);
+ if (port != null) {
+ ofPort = southbound.getOFPort(port);
+ }
+ if (ofPort == 0L) {
+ for (int i = 0; i < 5; i++) {
+ LOG.info("Looking for ofPort {}, try: {}", portName, i);
+ if (ofPort == 0L) {
+ TerminationPoint tp = southbound.readTerminationPoint(bridgeNode, null, portName);
+ if (tp != null) {
+ port = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
+ if (port != null) {
+ ofPort = southbound.getOFPort(port);
+ break;
+ }
+ }
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return ofPort;
+ }
+
+ private String getMacFromOptions(Node bridgeNode, String portName) {
+ String mac = null;
+ OvsdbTerminationPointAugmentation port = southbound.extractTerminationPointAugmentation(bridgeNode, portName);
+ LOG.info("getMac: portName: {}, bridgeNode: {},,, port: {}", portName, bridgeNode, port);
+ if (port != null && port.getOptions() != null) {
+ //mac = southbound.getOptionsValue(port.getOptions(), EXTERNAL_ID_VM_MAC);
+ for (Options option : port.getOptions()) {
+ LOG.info("getMac: option: {}", option);
+ if (option.getOption().equals(Constants.EXTERNAL_ID_VM_MAC)) {
+ mac = option.getValue();
+ break;
+ }
+ }
+ }
+ return mac;
+ }
+
+ private String getMacFromExternalIds(Node bridgeNode, String portName) {
+ String mac = null;
+ OvsdbTerminationPointAugmentation port = southbound.extractTerminationPointAugmentation(bridgeNode, portName);
+ LOG.info("getMac: portName: {}, bridgeNode: {},,, port: {}", portName, bridgeNode, port);
+ if (port != null && port.getInterfaceExternalIds() != null) {
+ mac = southbound.getInterfaceExternalIdsValue(port, Constants.EXTERNAL_ID_VM_MAC);
+ }
+ return mac;
+ }
+
+ @Override
+ public void setDependencies(ServiceReference serviceReference) {
+ nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
+ southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
+ sfcClassifierService =
+ (ISfcClassifierService) ServiceHelper.getGlobalInstance(ISfcClassifierService.class, this);
+ LOG.info("sfcClassifierService= {}", sfcClassifierService);
+ }
+}
+++ /dev/null
-/*
- * Copyright © 2015 Red Hat, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
-import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
-import org.opendaylight.ovsdb.openstack.netvirt.sfc.INetvirtSfcOF13Provider;
-import org.opendaylight.ovsdb.openstack.netvirt.sfc.SfcUtils;
-import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
-import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
-import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.Acl;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.Ace;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.Classifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.Bridges;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
-import org.osgi.framework.ServiceReference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider {
- private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcWorkaroundOF13Provider.class);
- private volatile NodeCacheManager nodeCacheManager;
- private volatile Southbound southbound;
- private MdsalUtils mdsalUtils;
- private SfcUtils sfcUtils;
- private SfcClassifierService sfcClassifierService;
-
- public NetvirtSfcWorkaroundOF13Provider(final DataBroker dataBroker, MdsalUtils mdsalUtils, SfcUtils sfcUtils) {
- Preconditions.checkNotNull(dataBroker, "Input dataBroker cannot be NULL!");
- Preconditions.checkNotNull(mdsalUtils, "Input mdsalUtils cannot be NULL!");
- Preconditions.checkNotNull(sfcUtils, "Input sfcUtils cannot be NULL!");
-
- this.mdsalUtils = mdsalUtils;
- this.sfcUtils = sfcUtils;
- this.setDependencies(null);
- }
-
- @Override
- public void addClassifierRules(Bridge bridge, Acl acl) {
-
- }
-
- @Override
- public void addClassifierRules(Bridges bridges, Acl acl) {
- Preconditions.checkNotNull(bridges, "Input bridges cannot be NULL!");
- Preconditions.checkNotNull(acl, "Input acl cannot be NULL!");
-
- for (Ace ace : acl.getAccessListEntries().getAce()) {
- processAclEntry(ace, bridges);
- }
- }
-
- @Override
- public void removeClassifierRules(Sff sff, Acl acl) {
-
- }
-
- @Override
- public void addClassifierRules(Acl acl) {
- String aclName = acl.getAclName();
- Classifiers classifiers = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, sfcUtils.getClassifierIid());
- if (classifiers == null) {
- LOG.debug("add: No Classifiers found");
- return;
- }
-
- LOG.debug("add: Classifiers: {}", classifiers);
- for (Classifier classifier : classifiers.getClassifier()) {
- if (classifier.getAcl().equals(aclName)) {
- if (classifier.getBridges() != null) {
- addClassifierRules(classifier.getBridges(), acl);
- }
- }
- }
- }
-
- @Override
- public void removeClassifierRules(Acl acl) {
-
- }
-
- private void processAclEntry(Ace entry, Bridges bridges) {
- Matches matches = entry.getMatches();
- Preconditions.checkNotNull(matches, "Input bridges cannot be NULL!");
-
- RenderedServicePath rsp = getRenderedServicePath(entry);
- if (rsp == null) {
- LOG.warn("Failed to get renderedServicePatch for entry: {}", entry);
- return;
- }
-
- //handleIngressClassifier();
- //handleEgressClassifier();
- //handleSfLoopback();
-
- }
-
- // loop through sf's:
- // - program arp responder
- // - program sf to sff
- // - program sff to sf
- private void handleSfWorkaround(RenderedServicePath rsp) {
-
- }
-
- private RenderedServicePath getRenderedServicePath (Ace entry) {
- RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
- LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
- if (sfcRedirect == null) {
- LOG.warn("processAClEntry: sfcRedirect is null");
- return null;
- }
-
- String sfcName = sfcRedirect.getRedirectSfc();
- ServiceFunctionPath sfp = sfcUtils.getSfp(sfcName);
- if (sfp == null || sfp.getName() == null) {
- LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
- return null;
- }
-
- LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcRedirect.getRedirectSfc(), sfp);
- // If RSP doesn't exist, create an RSP.
- String sfpName = sfp.getName().getValue();
- RenderedServicePath rsp = sfcUtils.getRspforSfp(sfpName);
- String rspName = sfp.getName().getValue() + "_rsp";
- if (rsp == null) {
- LOG.info("No configured RSP corresponding to SFP = {}, Creating new RSP = {}", sfpName, rspName);
- CreateRenderedPathInput rspInput = new CreateRenderedPathInputBuilder()
- .setParentServiceFunctionPath(sfpName)
- .setName(rspName)
- .setSymmetric(sfp.isSymmetric())
- .build();
- rsp = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, rspInput);
- if (rsp == null) {
- LOG.warn("failed to add RSP");
- return null;
- }
-
- // If SFP is symmetric, create RSP in the reverse direction.
- if (sfp.isSymmetric()) {
- LOG.info("SFP = {} is symmetric, installing RSP in the reverse direction!!", sfpName);
- String rspNameRev = rspName + "-Reverse";
- RenderedServicePath rspReverse = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
- sfcUtils.getRspId(rspNameRev));
- if (rspReverse == null) {
- rspReverse = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
- if (rspReverse == null) {
- LOG.warn("failed to add reverse RSP");
- return null;
- }
- }
- }
- }
- return rsp;
- }
-
- private void setDependencies(ServiceReference serviceReference) {
- nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
- southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
- sfcClassifierService = (SfcClassifierService) ServiceHelper.getGlobalInstance(SfcClassifierService.class, this);
- }
-}
package org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services;
+import com.google.common.collect.Lists;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.ISfcClassifierService;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.NshUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
+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.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEth;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
+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.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+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.FlowCookie;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
+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.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+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.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SfcClassifierService extends AbstractServiceInstance implements ConfigInterface, ISfcClassifierService {
+ private static final Logger LOG = LoggerFactory.getLogger(SfcClassifierService.class);
+ private static final short TABLE_0 = 0;
+ private static final short UDP_SHORT = 17;
+ private static int cookieCounter = 0;
+ private static final int FLOW_INGRESSCLASS = 1;
+ private static final int FLOW_SFINGRESS = 2;
+ private static final int FLOW_SFEGRESS = 3;
+ private static final int FLOW_SFARP = 4;
+ private static final int FLOW_EGRESSCLASS1 = 5;
+ private static final int FLOW_EGRESSCLASS2 = 6;
+ private static final int FLOW_SFCTABLE = 7;
-public class SfcClassifierService extends AbstractServiceInstance implements ConfigInterface {
public SfcClassifierService(Service service) {
super(service);
}
@Override
public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
- super.setDependencies(bundleContext.getServiceReference(SfcClassifierService.class.getName()), this);
+ super.setDependencies(bundleContext.getServiceReference(ISfcClassifierService.class.getName()), this);
}
@Override
public void setDependencies(Object impl) {}
+
+ private BigInteger getCookie(int index) {
+ String indexString = new String().format("%02d0000000000%04d", index, cookieCounter++);
+ return new BigInteger(indexString, 16);
+ }
+
+ @Override
+ public void programIngressClassifier(long dataPathId, String ruleName, Matches matches,
+ NshUtils nshHeader, long vxGpeOfPort, boolean write) {
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ MatchBuilder matchBuilder = buildMatch(matches);
+ flowBuilder.setMatch(MatchUtils.addNxRegMatch(
+ matchBuilder,
+ new MatchUtils.RegMatch(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL)).build());
+
+ String flowId = "sfcIngressClass_" + ruleName;// + "_" + nshHeader.getNshNsp();
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_INGRESSCLASS)));
+ flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_INGRESSCLASS)));
+
+ if (write) {
+ ActionBuilder ab = new ActionBuilder();
+ List<Action> actionList = new ArrayList<>();
+
+ ab.setAction(ActionUtils.nxMoveTunIdtoNshc2());
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ getNshAction(nshHeader, actionList);
+
+ ab.setAction(ActionUtils.outputAction(FlowUtils.getNodeConnectorId(dataPathId, vxGpeOfPort)));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ InstructionBuilder ib = new InstructionBuilder();
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ List<Instruction> instructions = Lists.newArrayList();
+ instructions.add(ib.build());
+
+ InstructionsBuilder isb = new InstructionsBuilder();
+ isb.setInstruction(instructions);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ @Override
+ public void programSfcTable(long dataPathId, long vxGpeOfPort, short goToTableId, boolean write) {
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort).build());
+
+ String flowId = "sfcTable_" + vxGpeOfPort;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(TABLE_0);
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ flowBuilder.setPriority(1000);
+ flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_SFCTABLE)));
+ flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_SFCTABLE)));
+
+ if (write) {
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib =
+ InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), goToTableId);
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ isb.setInstruction(instructions);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ @Override
+ public void programEgressClassifier1(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
+ int tunnelOfPort, int tunnelId, short gotoTableId, boolean write) {
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
+ MatchUtils.addNxNspMatch(matchBuilder, nsp);
+ flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nsi).build());
+
+ String flowId = "sfcEgressClass1_" + vxGpeOfPort;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(TABLE_0);
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_EGRESSCLASS1)));
+ flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_EGRESSCLASS1)));
+
+ if (write) {
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionBuilder ib = new InstructionBuilder();
+
+ /*List<Action> actionList = Lists.newArrayList();
+
+ ActionBuilder ab = new ActionBuilder();
+ ab.setAction(ActionUtils.nxMoveNshc2ToTunId());
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ actionList.add(ab.build());
+
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+ ib.setOrder(instructions.size());
+ ib.setKey(new InstructionKey(instructions.size()));
+ instructions.add(ib.build());*/
+
+ ib = InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), getTable());
+ ib.setOrder(instructions.size());
+ ib.setKey(new InstructionKey(instructions.size()));
+ instructions.add(ib.build());
+
+ isb.setInstruction(instructions);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ // add 3: same match, add in_port sf, priority=40k, move c2 to tun_id, reg0-1, nsp=0,nsi=0
+ @Override
+ public void programEgressClassifier2(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
+ int tunnelOfPort, int tunnelId, boolean write) {
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
+ MatchUtils.addNxRegMatch(matchBuilder,
+ new MatchUtils.RegMatch(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL)).build();
+ MatchUtils.addNxNspMatch(matchBuilder, nsp);
+ flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nsi).build());
+
+ String flowId = "sfcEgressClass2_" + vxGpeOfPort;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_EGRESSCLASS2)));
+ flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_EGRESSCLASS2)));
+
+ if (write) {
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ List<Action> actionList = Lists.newArrayList();
+
+ ActionBuilder ab = new ActionBuilder();
+
+ // don't do this, need it to match on the resubmit side and get past table 10 so it isn't reclassified
+ //ab.setAction(ActionUtils.nxSetNspAction((long)(0)));
+ //ab.setOrder(0);
+ //ab.setKey(new ActionKey(0));
+ //actionList.add(ab.build());
+
+ ab.setAction(ActionUtils.nxResubmitAction(tunnelOfPort, TABLE_0));
+ ab.setOrder(actionList.size());
+ ab.setKey(new ActionKey(actionList.size()));
+ actionList.add(ab.build());
+
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+ InstructionBuilder ib = new InstructionBuilder();
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ isb.setInstruction(instructions);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ // packet from sf to sff that need to go out local
+ @Override
+ public void program_sfEgress(long dataPathId, int dstPort, boolean write) {
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT);
+ MatchUtils.addLayer4Match(matchBuilder, UDP_SHORT, 0, dstPort);
+ flowBuilder.setMatch(MatchUtils.addNxRegMatch(
+ matchBuilder, new MatchUtils.RegMatch(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL)).build());
+
+ String flowId = "sfEgress_" + dstPort;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(getTable());
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_SFEGRESS)));
+ flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_SFEGRESS)));
+
+ if (write) {
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionUtils.createLocalInstructions(ib, dataPathId);
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ isb.setInstruction(instructions);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ // looped back sff to sf packets
+ @Override
+ public void program_sfIngress(long dataPathId, int dstPort, long sfOfPort,
+ String ipAddress, String sfDplName, boolean write) {
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT);
+ Ipv4Prefix ipCidr = MatchUtils.iPv4PrefixFromIPv4Address(ipAddress);
+ MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(ipCidr));
+ flowBuilder.setMatch(MatchUtils.addLayer4Match(matchBuilder, UDP_SHORT, 0, dstPort).build());
+
+ String flowId = "sfIngress_" + dstPort + "_" + ipAddress;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(TABLE_0);
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_SFINGRESS)));
+ flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_SFINGRESS)));
+
+ if (write) {
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionUtils.createOutputPortInstructions(ib, dataPathId, sfOfPort);
+
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ isb.setInstruction(instructions);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ @Override
+ public void programStaticArpEntry(long dataPathId, long ofPort, String macAddressStr,
+ String ipAddress, boolean write) {
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ MacAddress macAddress = new MacAddress(macAddressStr);
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(Constants.ARP_ETHERTYPE));
+ MatchUtils.createArpDstIpv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(ipAddress));
+ flowBuilder.setMatch(matchBuilder.build());
+
+ String flowId = "ArpResponder_" + ipAddress;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(TABLE_0);
+ flowBuilder.setKey(key);
+ flowBuilder.setPriority(1024);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_SFARP)));
+ flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_SFARP)));
+
+ if (write == true) {
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ ActionBuilder ab = new ActionBuilder();
+ List<Action> actionList = Lists.newArrayList();
+
+ // Move Eth Src to Eth Dst
+ ab.setAction(ActionUtils.nxMoveEthSrcToEthDstAction());
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ actionList.add(ab.build());
+
+ // Set Eth Src
+ ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
+ ab.setOrder(1);
+ ab.setKey(new ActionKey(1));
+ actionList.add(ab.build());
+
+ // Set ARP OP
+ ab.setAction(ActionUtils.nxLoadArpOpAction(BigInteger.valueOf(0x02L)));
+ ab.setOrder(2);
+ ab.setKey(new ActionKey(2));
+ actionList.add(ab.build());
+
+ // Move ARP SHA to ARP THA
+ ab.setAction(ActionUtils.nxMoveArpShaToArpThaAction());
+ ab.setOrder(3);
+ ab.setKey(new ActionKey(3));
+ actionList.add(ab.build());
+
+ // Move ARP SPA to ARP TPA
+ ab.setAction(ActionUtils.nxMoveArpSpaToArpTpaAction());
+ ab.setOrder(4);
+ ab.setKey(new ActionKey(4));
+ actionList.add(ab.build());
+
+ // Load Mac to ARP SHA
+ ab.setAction(ActionUtils.nxLoadArpShaAction(macAddress));
+ ab.setOrder(5);
+ ab.setKey(new ActionKey(5));
+ actionList.add(ab.build());
+
+ // Load IP to ARP SPA
+ ab.setAction(ActionUtils.nxLoadArpSpaAction(ipAddress));
+ ab.setOrder(6);
+ ab.setKey(new ActionKey(6));
+ actionList.add(ab.build());
+
+ // Output of InPort
+ ab.setAction(ActionUtils.outputAction(
+ FlowUtils.getSpecialNodeConnectorId(dataPathId, OutputPortValues.INPORT.toString())));
+ ab.setOrder(7);
+ ab.setKey(new ActionKey(7));
+ actionList.add(ab.build());
+
+ // Create Apply Actions Instruction
+ aab.setAction(actionList);
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ isb.setInstruction(instructions);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ private List<Action> getNshAction(NshUtils header, List<Action> actionList) {
+ // Build the Actions to Add the NSH Header
+ org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC1Load =
+ ActionUtils.nxLoadNshc1RegAction(header.getNshMetaC1());
+ org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC2Load =
+ ActionUtils.nxLoadNshc2RegAction(header.getNshMetaC2());
+ org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nspLoad =
+ ActionUtils.nxSetNspAction(header.getNshNsp());
+ org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nsiLoad =
+ ActionUtils.nxSetNsiAction(header.getNshNsi());
+ org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunVnid =
+ ActionUtils.nxLoadTunIdAction(BigInteger.valueOf(header.getNshNsp()), false);
+ org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunDest =
+ ActionUtils.nxLoadTunIPv4Action(header.getNshTunIpDst().getValue(), false);
+
+ int count = actionList.size();
+ actionList.add(new ActionBuilder()
+ .setKey(new ActionKey(count)).setOrder(count++).setAction(nshC1Load).build());
+ //actionList.add(new ActionBuilder()
+ // .setKey(new ActionKey(count)).setOrder(count++).setAction(nshC2Load).build());
+ actionList.add(new ActionBuilder()
+ .setKey(new ActionKey(count)).setOrder(count++).setAction(nspLoad).build());
+ actionList.add(new ActionBuilder()
+ .setKey(new ActionKey(count)).setOrder(count++).setAction(nsiLoad).build());
+ actionList.add(new ActionBuilder()
+ .setKey(new ActionKey(count)).setOrder(count++).setAction(loadChainTunDest).build());
+ actionList.add(new ActionBuilder()
+ .setKey(new ActionKey(count)).setOrder(count).setAction(loadChainTunVnid).build());
+ return actionList;
+ }
+
+ public MatchBuilder buildMatch(Matches matches) {
+ MatchBuilder matchBuilder = new MatchBuilder();
+
+ if (matches.getAceType() instanceof AceIp) {
+ AceIp aceIp = (AceIp)matches.getAceType();
+ if (aceIp.getAceIpVersion() instanceof AceIpv4) {
+ //AceIpv4 aceIpv4 = (AceIpv4) aceIp.getAceIpVersion();
+ //MatchUtils.createSrcL3IPv4Match(matchBuilder, aceIpv4.getSourceIpv4Network());
+ //MatchUtils.createDstL3IPv4Match(matchBuilder, aceIpv4.getDestinationIpv4Network());
+ MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
+ MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0,
+ aceIp.getDestinationPortRange().getLowerPort().getValue().intValue());
+ } else {
+ MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
+ MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0,
+ aceIp.getDestinationPortRange().getLowerPort().getValue().intValue());
+ }
+ } else if (matches.getAceType() instanceof AceEth) {
+ AceEth aceEth = (AceEth) matches.getAceType();
+ MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(aceEth.getSourceMacAddress().getValue()));
+ MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(aceEth.getDestinationMacAddress().getValue()),
+ new MacAddress(aceEth.getDestinationMacAddressMask().getValue()));
+ }
+
+ LOG.info("buildMatch: {}", matchBuilder.build());
+ return matchBuilder;
+ }
}
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
+import com.google.common.collect.Maps;
+import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Assert;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.SfcClassifier;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.AclUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ClassifierUtils;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionChainUtils;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionPathUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionForwarderUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionUtils;
import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.entry.SfDataPlaneLocator;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.entry.SfDataPlaneLocatorBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChains;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChainsBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunctionBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarders;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwardersBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionary;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionaryBuilder;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.SffDataPlaneLocator;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.SffDataPlaneLocatorBuilder;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.service.function.dictionary.SffSfDataPlaneLocatorBuilder;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.sff.data.plane.locator.DataPlaneLocatorBuilder;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sft.rev140701.Dpi;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sft.rev140701.Firewall;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessListsBuilder;
private static SfcUtils sfcUtils = new SfcUtils();
private static ServiceFunctionUtils serviceFunctionUtils = new ServiceFunctionUtils();
private static ServiceFunctionForwarderUtils serviceFunctionForwarderUtils = new ServiceFunctionForwarderUtils();
+ private static ServiceFunctionChainUtils serviceFunctionChainUtils = new ServiceFunctionChainUtils();
+ private static ServiceFunctionPathUtils serviceFunctionPathUtils = new ServiceFunctionPathUtils();
private static MdsalUtils mdsalUtils;
private static AtomicBoolean setup = new AtomicBoolean(false);
private static SouthboundUtils southboundUtils;
public static final String INTEGRATION_BRIDGE_NAME = "br-int";
private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
private static final String OVSDB_TRACE = "ovsdb.trace";
+ private static final String SF1NAME = "firewall-72";
+ private static final String SF2NAME = "dpi-72";
+ private static final String SF1IP = "10.2.1.1";//"192.168.50.70";//"192.168.120.31";
+ private static final String SF2IP = "10.2.1.2";
+ private static final String SF1DPLNAME = "sf1";
+ private static final String SF2DPLNAME = "sf2";
+ private static final String SFF1IP = "127.0.0.1";
+ private static final String SFF2IP = "127.0.0.1";
+ private static final String SFF1NAME = "SFF1";
+ private static final String SFF2NAME = "SFF2";
+ private static final String SFFDPL1NAME = "vxgpe";
+ private static final String SFFDPL2NAME = "vxgpe";
+ private static final String SN1NAME = "OVSDB1";
+ private static final String SN2NAME = "OVSDB2";
+ private static final String BRIDGE1NAME= "br-int";
+ private static final String BRIDGE2NAME= "br-int";
+ private static final String ACLNAME= "httpAcl";
+ private static final String SFCNAME = "SFC";
+ private static final int GPEPORT = 6633;
@Override
public String getModuleName() {
editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
"log4j.logger.org.opendaylight.ovsdb",
LogLevelOption.LogLevel.TRACE.name())),
+ //editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
+ // "log4j.logger.org.opendaylight.ovsdb",
+ // LogLevelOption.LogLevel.TRACE.name()),
editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
logConfiguration(NetvirtSfcIT.class),
LogLevel.INFO.name()),
"log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.sfc",
LogLevel.TRACE.name()),
editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
- "log4j.logger.org.opendaylight.ovsdb.sfc",
+ "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13",
+ LogLevel.TRACE.name()),
+ editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
+ "log4j.logger.org.opendaylight.sfc",
LogLevel.TRACE.name()),
super.getLoggingOption());
}
assertTrue(true);
}
- private AccessListsBuilder setAccessLists () {
+ private AccessListsBuilder accessListsBuilder() {
MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
- ActionsBuilder actionsBuilder = aclUtils.actionsBuilder(new ActionsBuilder(), Boolean.TRUE);
- AceBuilder accessListEntryBuilder = aclUtils.aceBuilder(
- new AceBuilder(), "http", matchesBuilder, actionsBuilder);
- AccessListEntriesBuilder accessListEntriesBuilder = aclUtils.accessListEntriesBuidler(
- new AccessListEntriesBuilder(), accessListEntryBuilder);
- AclBuilder accessListBuilder = aclUtils.aclBuilder(new AclBuilder(),
- "http", accessListEntriesBuilder);
- AccessListsBuilder accessListsBuilder = aclUtils.accessListsBuidler(new AccessListsBuilder(),
- accessListBuilder);
+ LOG.info("Matches: {}", matchesBuilder.build());
+ //ActionsBuilder actionsBuilder = aclUtils.actionsBuilder(new ActionsBuilder(), Boolean.TRUE);
+ ActionsBuilder actionsBuilder = aclUtils.actionsBuilder(new ActionsBuilder(), SFCNAME);
+ AceBuilder accessListEntryBuilder =
+ aclUtils.aceBuilder(new AceBuilder(), "httpRule", matchesBuilder, actionsBuilder);
+ AccessListEntriesBuilder accessListEntriesBuilder =
+ aclUtils.accessListEntriesBuidler(new AccessListEntriesBuilder(), accessListEntryBuilder);
+ AclBuilder accessListBuilder =
+ aclUtils.aclBuilder(new AclBuilder(), ACLNAME, accessListEntriesBuilder);
+ AccessListsBuilder accessListsBuilder =
+ aclUtils.accesslistsbuilder(new AccessListsBuilder(), accessListBuilder);
LOG.info("AccessLists: {}", accessListsBuilder.build());
return accessListsBuilder;
}
@Test
public void testAccessLists() throws InterruptedException {
- testModel(setAccessLists(), AccessLists.class, 0);
+ testModel(accessListsBuilder(), AccessLists.class, 0);
}
- private ClassifiersBuilder setClassifiers() {
- SffBuilder sffBuilder = classifierUtils.sffBuilder(new SffBuilder(), "sffname");
+ private ClassifiersBuilder classifiersBuilder() {
+ SffBuilder sffBuilder = classifierUtils.sffBuilder(new SffBuilder(), SFF1NAME);
SffsBuilder sffsBuilder = classifierUtils.sffsBuilder(new SffsBuilder(), sffBuilder);
ClassifierBuilder classifierBuilder = classifierUtils.classifierBuilder(new ClassifierBuilder(),
- "classifierName", "aclName", sffsBuilder);
+ "classifierName", ACLNAME, sffsBuilder);
ClassifiersBuilder classifiersBuilder = classifierUtils.ClassifiersBuilder(new ClassifiersBuilder(),
classifierBuilder);
LOG.info("Classifiers: {}", classifiersBuilder.build());
@Test
public void testClassifiers() throws InterruptedException {
- testModel(setClassifiers(), Classifiers.class, 0);
+ testModel(classifiersBuilder(), Classifiers.class, 0);
}
private SfcBuilder netvirtSfcBuilder() {
testModel(netvirtSfcBuilder(), Sfc.class, 0);
}
- private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz, long wait)
- throws InterruptedException {
+ private <T extends DataObject> void testModelPut(Builder<T> builder, Class<T> clazz) {
InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
assertTrue(mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, path, builder.build()));
T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
assertNotNull(clazz.getSimpleName() + " should not be null", result);
- Thread.sleep(wait);
+ }
+
+ private <T extends DataObject> void testModelDelete(Builder<T> builder, Class<T> clazz)
+ throws InterruptedException {
+ InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
assertTrue("Failed to remove " + clazz.getSimpleName(),
mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, path));
- result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
+ T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
assertNull(clazz.getSimpleName() + " should be null", result);
}
+ private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz, long wait)
+ throws InterruptedException {
+ testModelPut(builder, clazz);
+ Thread.sleep(wait);
+ testModelDelete(builder, clazz);
+ }
+
private ServiceFunctionsBuilder serviceFunctionsBuilder() {
- SfDataPlaneLocatorBuilder sfDataPlaneLocator =
- serviceFunctionUtils.sfDataPlaneLocatorBuilder(new SfDataPlaneLocatorBuilder(),
- "192.168.120.31", 6633, "testDpl1-1234-uuid", "testSff1");
- List<SfDataPlaneLocator> sfDataPlaneLocatorList = serviceFunctionUtils.list(
- new ArrayList<SfDataPlaneLocator>(), sfDataPlaneLocator);
+ String sf1Name = SF1NAME;
+ String sf1Ip = SF1IP;
+ String sff1Ip = SF1IP;
+ String sff1Name = SFF1NAME;
+ String sf1DplName = SF1DPLNAME;
+ String sn1Name = SN1NAME;
+ String bridge1Name= BRIDGE1NAME;
+ String sf2Name = SF2NAME;
+ String sf2Ip = SF2IP;
+ String sff2Ip = SF2IP;
+ String sff2Name = SFF2NAME;
+ String sf2DplName = SF2DPLNAME;
+ String sn2Name = SN2NAME;
+ String bridge2Name= BRIDGE2NAME;
+ int port = GPEPORT;
+
ServiceFunctionBuilder serviceFunctionBuilder =
- serviceFunctionUtils.serviceFunctionBuidler(new ServiceFunctionBuilder(),
- "192.168.120.31", "testSf", sfDataPlaneLocatorList, Firewall.class);
+ serviceFunctionUtils.serviceFunctionBuilder(sf1Ip, port, sf1DplName, sff1Name, sf1Name);
List<ServiceFunction> serviceFunctionList = serviceFunctionUtils.list(
new ArrayList<ServiceFunction>(), serviceFunctionBuilder);
- sfDataPlaneLocator =
- serviceFunctionUtils.sfDataPlaneLocatorBuilder(new SfDataPlaneLocatorBuilder(),
- "192.168.120.32", 6633, "testDpl2-1234-uuid", "testSff2");
- sfDataPlaneLocatorList = serviceFunctionUtils.list(
- new ArrayList<SfDataPlaneLocator>(), sfDataPlaneLocator);
- serviceFunctionBuilder =
- serviceFunctionUtils.serviceFunctionBuidler(new ServiceFunctionBuilder(),
- "192.168.120.32", "testSf2", sfDataPlaneLocatorList, Dpi.class);
- serviceFunctionList = serviceFunctionUtils.list(
- serviceFunctionList, serviceFunctionBuilder);
+ //serviceFunctionBuilder =
+ // serviceFunctionUtils.serviceFunctionBuilder(sf2Ip, port, sffDpl2Name, sff2Name, sf2Name);
+ //serviceFunctionList = serviceFunctionUtils.list(
+ // serviceFunctionList, serviceFunctionBuilder);
ServiceFunctionsBuilder serviceFunctionsBuilder =
serviceFunctionUtils.serviceFunctionsBuilder(new ServiceFunctionsBuilder(),
}
private ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder() {
- String sf1Name = "firewall-72";
- String sff1Ip = "192.168.120.31";
- String sff1Name = "SFF1";
- String sffDpl1Name = "sfc-tun2";
- String sn1Name = "OVSDB2";
- String bridge1Name= "sw2";
- int port = 6633;
-
- DataPlaneLocatorBuilder dataPlaneLocatorBuilder =
- serviceFunctionForwarderUtils.dataPlaneLocatorBuilder(
- new DataPlaneLocatorBuilder(), sff1Ip, port);
- SffDataPlaneLocatorBuilder sffDataPlaneLocatorBuilder =
- serviceFunctionForwarderUtils.sffDataPlaneLocatorBuilder(
- new SffDataPlaneLocatorBuilder(), dataPlaneLocatorBuilder, sffDpl1Name);
- List<SffDataPlaneLocator> sffDataPlaneLocatorList = serviceFunctionForwarderUtils.list(
- new ArrayList<SffDataPlaneLocator>(), sffDataPlaneLocatorBuilder);
-
- SffSfDataPlaneLocatorBuilder sffSfDataPlaneLocatorBuilder =
- serviceFunctionForwarderUtils.sffSfDataPlaneLocatorBuilder(
- new SffSfDataPlaneLocatorBuilder(), sff1Ip, port);
- ServiceFunctionDictionaryBuilder serviceFunctionDictionaryBuilder =
- serviceFunctionForwarderUtils.serviceFunctionDictionaryBuilder(
- new ServiceFunctionDictionaryBuilder(), sf1Name, Firewall.class,
- sffSfDataPlaneLocatorBuilder);
- List<ServiceFunctionDictionary> serviceFunctionDictionaryList = serviceFunctionForwarderUtils.list(
- new ArrayList<ServiceFunctionDictionary>(), serviceFunctionDictionaryBuilder);
+ String sf1Name = SF1NAME;
+ String sf1Ip = SF1IP;
+ String sff1Ip = SFF1IP;
+ String sff1Name = SFF1NAME;
+ String sffDpl1Name = SFFDPL1NAME;
+ String sn1Name = SN1NAME;
+ String bridge1Name= BRIDGE1NAME;
+ String sf2Name = SF2NAME;
+ String sf2Ip = SF2IP;
+ String sff2Ip = SFF2IP;
+ String sff2Name = SFF2NAME;
+ String sffDpl2Name = SFFDPL2NAME;
+ String sn2Name = SN2NAME;
+ String bridge2Name= BRIDGE2NAME;
+ String aclName = ACLNAME;
+ int port = GPEPORT;
ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder =
serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder(
- new ServiceFunctionForwarderBuilder(), sff1Name, sn1Name, bridge1Name,
- sffDataPlaneLocatorList, serviceFunctionDictionaryList);
+ sff1Name, sff1Ip, port, sffDpl1Name, sf1Name, sf1Ip, sn1Name, bridge1Name, Firewall.class);
List<ServiceFunctionForwarder> serviceFunctionForwarderList = serviceFunctionForwarderUtils.list(
new ArrayList<ServiceFunctionForwarder>(), serviceFunctionForwarderBuilder);
+
+ //serviceFunctionForwarderBuilder =
+ // serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder(
+ // sff2Name, sff2Ip, port, sffDpl2Name, sf2Name, sff2Ip, sn2Name, bridge2Name, Dpi.class);
+ //serviceFunctionForwarderList = serviceFunctionForwarderUtils.list(
+ // serviceFunctionForwarderList, serviceFunctionForwarderBuilder);
+
ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder =
serviceFunctionForwarderUtils.serviceFunctionForwardersBuilder(
new ServiceFunctionForwardersBuilder(), serviceFunctionForwarderList);
return serviceFunctionForwardersBuilder;
}
+ private ServiceFunctionChainsBuilder serviceFunctionChainsBuilder() {
+ String sf1Name = "firewall-abstract1";
+ String sf2Name = "dpi-abstract1";
+ String sfcName = SFCNAME;
+
+ SfcServiceFunctionBuilder sfcServiceFunctionBuilder = serviceFunctionChainUtils.sfcServiceFunctionBuilder(
+ new SfcServiceFunctionBuilder(), sf1Name, Firewall.class);
+ List<SfcServiceFunction> sfcServiceFunctionList =
+ serviceFunctionChainUtils.list(new ArrayList<SfcServiceFunction>(), sfcServiceFunctionBuilder);
+
+ //sfcServiceFunctionBuilder = serviceFunctionChainUtils.sfcServiceFunctionBuilder(
+ // sfcServiceFunctionBuilder, sf2Name, Dpi.class);
+ //sfcServiceFunctionList = serviceFunctionChainUtils.list(sfcServiceFunctionList, sfcServiceFunctionBuilder);
+
+ ServiceFunctionChainBuilder serviceFunctionChainBuilder =
+ serviceFunctionChainUtils.serviceFunctionChainBuilder(
+ new ServiceFunctionChainBuilder(), sfcName, false, sfcServiceFunctionList);
+ ServiceFunctionChainsBuilder serviceFunctionChainsBuilder =
+ serviceFunctionChainUtils.serviceFunctionChainsBuilder(
+ new ServiceFunctionChainsBuilder(),
+ serviceFunctionChainUtils.list(new ArrayList<ServiceFunctionChain>(),
+ serviceFunctionChainBuilder));
+ LOG.info("ServiceFunctionChains: {}", serviceFunctionChainBuilder.build());
+ return serviceFunctionChainsBuilder;
+ }
+
+ private ServiceFunctionPathsBuilder serviceFunctionPathsBuilder() {
+ String sfpName = "SFC-Path";
+ String sfcName = "SFC";
+ short startingIndex = 255;
+
+ ServiceFunctionPathBuilder serviceFunctionPathBuilder =
+ serviceFunctionPathUtils.serviceFunctionPathBuilder(
+ new ServiceFunctionPathBuilder(), sfpName, sfcName, startingIndex, false);
+ ServiceFunctionPathsBuilder serviceFunctionPathsBuilder =
+ serviceFunctionPathUtils.serviceFunctionPathsBuilder(
+ serviceFunctionPathUtils.list(new ArrayList<ServiceFunctionPath>(),
+ serviceFunctionPathBuilder));
+ LOG.info("ServiceFunctionPaths: {}", serviceFunctionPathsBuilder.build());
+ return serviceFunctionPathsBuilder;
+ }
+
@Test
public void testSfcModel() throws InterruptedException {
testModel(serviceFunctionsBuilder(), ServiceFunctions.class, 3000);
testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class, 3000);
+ testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class, 3000);
+ testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class, 3000);
+ }
+
+ @Test
+ public void testSfcModels() throws InterruptedException {
+ String bridgeName = INTEGRATION_BRIDGE_NAME;
+ ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
+ assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
+ Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
+ assertNotNull("node is not connected", ovsdbNode);
+
+ Thread.sleep(5000);
+ Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
+ assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
+ long datapathId = southbound.getDataPathId(bridgeNode);
+
+ Map<String, String> externalIds = Maps.newHashMap();
+ externalIds.put("attached-mac", "f6:00:00:0f:00:01");
+ southboundUtils.addTerminationPoint(bridgeNode, null, SF1DPLNAME, "internal", null, externalIds);
+ southboundUtils.addTerminationPoint(bridgeNode, null, "vm1", "internal");
+ southboundUtils.addTerminationPoint(bridgeNode, null, "vm2", "internal");
+ Map<String, String> options = Maps.newHashMap();
+ options.put("key", "flow");
+ options.put("remote_ip", "192.168.120.32");
+ southboundUtils.addTerminationPoint(bridgeNode, null, "vx", "vxlan", options, null);
+ Thread.sleep(1000);
+
+ testModelPut(serviceFunctionsBuilder(), ServiceFunctions.class);
+ testModelPut(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class);
+ testModelPut(serviceFunctionChainsBuilder(), ServiceFunctionChains.class);
+ testModelPut(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class);
+
+ Thread.sleep(5000);
+
+ testModelPut(accessListsBuilder(), AccessLists.class);
+ testModelPut(classifiersBuilder(), Classifiers.class);
+
+ Thread.sleep(10000);
+
+ ISfcClassifierService sfcClassifierService = (ISfcClassifierService) ServiceHelper.getGlobalInstance(ISfcClassifierService.class, this);
+ LOG.info("SfcClassifierService: {}", sfcClassifierService);
+ readwait();
+ //sfcClassifierService.programIngressClassifier(datapathId);
+
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
+ FlowBuilder flowBuilder = getSfcIngressClassifierFlowBuilder();
+ Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+ assertNotNull("Could not find flow in config", flow);
+ flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+ assertNotNull("Could not find flow in operational", flow);
+
+ assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
+ Thread.sleep(1000);
+ assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
}
/*
return flowBuilder;
}
+ private FlowBuilder getSfcIngressClassifierFlowBuilder() {
+ FlowBuilder flowBuilder = new FlowBuilder();
+ String flowId = "sfcClass_" + "httpRule";
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setTableId((short)10);
+ return flowBuilder;
+ }
+
private Flow getFlow (FlowBuilder flowBuilder, NodeBuilder nodeBuilder, LogicalDatastoreType store)
throws InterruptedException {
Flow flow = null;
for (int i = 0; i < 10; i++) {
flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
if (flow != null) {
- LOG.info("getFlow: flow({}): {}", store, flow);
+ LOG.info("getFlow: flow: {}: {}", store, flow);
break;
}
Thread.sleep(1000);
}
return flow;
}
+
+ private void readwait() {
+ try {
+ System.in.read();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev150611.acl.transport.header.fields.DestinationPortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfcBuilder;
public class AclUtils extends AbstractUtils {
public MatchesBuilder matchesBuilder(MatchesBuilder matchesBuilder, int destPort) {
return actionsBuilder.setPacketHandling(new PermitBuilder().setPermit(permit).build());
}
+ public ActionsBuilder actionsBuilder(ActionsBuilder actionsBuilder, String sfcName) {
+ RedirectToSfcBuilder redirectToSfcBuilder = new RedirectToSfcBuilder().setSfcName(sfcName);
+
+ return actionsBuilder.addAugmentation(RedirectToSfc.class, redirectToSfcBuilder.build());
+ }
+
public AceBuilder aceBuilder(AceBuilder accessListEntryBuilder,
String ruleName,
MatchesBuilder matchesBuilder,
}
public AccessListEntriesBuilder accessListEntriesBuidler(AccessListEntriesBuilder accessListEntriesBuilder,
- AceBuilder accessListEntryBuilder) {
- List<Ace> accessListEntriesList = new ArrayList<>();
- accessListEntriesList.add(accessListEntryBuilder.build());
+ AceBuilder aceBuilder) {
+ List<Ace> aceList = new ArrayList<>();
+ aceList.add(aceBuilder.build());
- return accessListEntriesBuilder;
+ return accessListEntriesBuilder.setAce(aceList);
}
- public AclBuilder aclBuilder(AclBuilder accessListBuilder,
+ public AclBuilder aclBuilder(AclBuilder aclBuilder,
String aclName,
AccessListEntriesBuilder accessListEntriesBuilder) {
- return accessListBuilder
+ return aclBuilder
.setAclName(aclName)
.setAccessListEntries(accessListEntriesBuilder.build());
}
- public AccessListsBuilder accessListsBuidler(AccessListsBuilder accessListsBuilder,
- AclBuilder accessListBuilder) {
- List<Acl> accessListList = new ArrayList<>();
- accessListList.add(accessListBuilder.build());
- accessListsBuilder.setAcl(accessListList);
+ public AccessListsBuilder accesslistsbuilder(AccessListsBuilder accessListsBuilder,
+ AclBuilder aclBuilder) {
+ List<Acl> aclList = new ArrayList<>();
+ aclList.add(aclBuilder.build());
- return accessListsBuilder;
+ return accessListsBuilder.setAcl(aclList);
}
}
--- /dev/null
+/*
+ * Copyright © 2015 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.sfc.utils;
+
+import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfcName;
+
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChainsBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunctionBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sft.rev140701.ServiceFunctionTypeIdentity;
+
+public class ServiceFunctionChainUtils extends AbstractUtils {
+ public SfcServiceFunctionBuilder sfcServiceFunctionBuilder(SfcServiceFunctionBuilder sfcServiceFunctionBuilder,
+ String name,
+ Class<? extends ServiceFunctionTypeIdentity> type) {
+ return sfcServiceFunctionBuilder
+ .setName(name)
+ .setType(type);
+ }
+
+ public ServiceFunctionChainBuilder serviceFunctionChainBuilder(
+ ServiceFunctionChainBuilder serviceFunctionChainBuilder, String name, Boolean symmetric,
+ List<SfcServiceFunction> sfcServiceFunctionList) {
+
+ return serviceFunctionChainBuilder
+ .setName(SfcName.getDefaultInstance(name))
+ .setSymmetric(symmetric)
+ .setSfcServiceFunction(sfcServiceFunctionList);
+ }
+
+ public ServiceFunctionChainsBuilder serviceFunctionChainsBuilder(
+ ServiceFunctionChainsBuilder serviceFunctionChainsBuilder,
+ List<ServiceFunctionChain> serviceFunctionChainBuilderList) {
+
+ return serviceFunctionChainsBuilder.setServiceFunctionChain(serviceFunctionChainBuilderList);
+ }
+}
package org.opendaylight.ovsdb.openstack.netvirt.sfc.utils;
+import java.util.ArrayList;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffDataPlaneLocatorName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SnName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsBridgeAugmentationBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsLocatorOptionsAugmentation;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsLocatorOptionsAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.bridge.OvsBridgeBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.options.OvsOptionsBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwardersBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.sff.data.plane.locator.DataPlaneLocatorBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sft.rev140701.ServiceFunctionTypeIdentity;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
public class ServiceFunctionForwarderUtils extends AbstractUtils {
public OvsOptionsBuilder ovsOptionsBuilder(OvsOptionsBuilder ovsOptionsBuilder, int port) {
.setSffSfDataPlaneLocator(sffSfDataPlaneLocatorBuilder.build());
}
+ public OvsBridgeBuilder ovsBridgeBuilder(OvsBridgeBuilder ovsBridgeBuilder, String bridgeNme) {
+ return ovsBridgeBuilder.setBridgeName(bridgeNme);
+ }
+
public ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder(
ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder,
String sffName, String serviceNodeName, String bridgeName,
List<SffDataPlaneLocator> sffDataPlaneLocatorList,
List<ServiceFunctionDictionary> serviceFunctionDictionaryList) {
+ SffOvsBridgeAugmentationBuilder sffOvsBridgeAugmentationBuilder = new SffOvsBridgeAugmentationBuilder();
+ sffOvsBridgeAugmentationBuilder.setOvsBridge(ovsBridgeBuilder(new OvsBridgeBuilder(), bridgeName).build());
+
return serviceFunctionForwarderBuilder
.setName(new SffName(sffName))
.setServiceNode(new SnName(serviceNodeName))
.setServiceFunctionDictionary(serviceFunctionDictionaryList)
- .setSffDataPlaneLocator(sffDataPlaneLocatorList);
+ .setSffDataPlaneLocator(sffDataPlaneLocatorList)
+ .addAugmentation(SffOvsBridgeAugmentation.class, sffOvsBridgeAugmentationBuilder.build());
}
public ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder(
List<ServiceFunctionForwarder> serviceFunctionForwarderList) {
return serviceFunctionForwardersBuilder.setServiceFunctionForwarder(serviceFunctionForwarderList);
}
+
+ public ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder(
+ String sffName, String sffIp, int port, String sffDplName,
+ String sfName, String sfIp, String snName, String bridgeName,
+ Class<? extends ServiceFunctionTypeIdentity> type) {
+
+ DataPlaneLocatorBuilder dataPlaneLocatorBuilder =
+ dataPlaneLocatorBuilder(new DataPlaneLocatorBuilder(), sffIp, port);
+ SffDataPlaneLocatorBuilder sffDataPlaneLocatorBuilder =
+ sffDataPlaneLocatorBuilder( new SffDataPlaneLocatorBuilder(), dataPlaneLocatorBuilder, sffDplName);
+ List<SffDataPlaneLocator> sffDataPlaneLocatorList =
+ list(new ArrayList<SffDataPlaneLocator>(), sffDataPlaneLocatorBuilder);
+
+ SffSfDataPlaneLocatorBuilder sffSfDataPlaneLocatorBuilder =
+ sffSfDataPlaneLocatorBuilder(new SffSfDataPlaneLocatorBuilder(), sffIp, port);
+ ServiceFunctionDictionaryBuilder serviceFunctionDictionaryBuilder =
+ serviceFunctionDictionaryBuilder(new ServiceFunctionDictionaryBuilder(), sfName, type,
+ sffSfDataPlaneLocatorBuilder);
+ List<ServiceFunctionDictionary> serviceFunctionDictionaryList =
+ list(new ArrayList<ServiceFunctionDictionary>(), serviceFunctionDictionaryBuilder);
+
+ ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder =
+ serviceFunctionForwarderBuilder(
+ new ServiceFunctionForwarderBuilder(), sffName, snName, bridgeName,
+ sffDataPlaneLocatorList, serviceFunctionDictionaryList);
+ return serviceFunctionForwarderBuilder;
+ }
}
--- /dev/null
+/*
+ * Copyright © 2015 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.sfc.utils;
+
+import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfcName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
+
+public class ServiceFunctionPathUtils extends AbstractUtils {
+ public ServiceFunctionPathBuilder serviceFunctionPathBuilder(
+ ServiceFunctionPathBuilder serviceFunctionPathBuilder,
+ String sfpName, String sfcName, short startingIndex, Boolean symmetric) {
+
+ return serviceFunctionPathBuilder
+ .setSymmetric(symmetric)
+ .setName(SfpName.getDefaultInstance(sfpName))
+ .setServiceChainName(SfcName.getDefaultInstance(sfcName))
+ .setStartingIndex(startingIndex);
+ }
+
+ public ServiceFunctionPathsBuilder serviceFunctionPathsBuilder(
+ List<ServiceFunctionPath> serviceFunctionPathList) {
+
+ return new ServiceFunctionPathsBuilder().setServiceFunctionPath(serviceFunctionPathList);
+ }
+}
package org.opendaylight.ovsdb.openstack.netvirt.sfc.utils;
+import java.util.ArrayList;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfDataPlaneLocatorName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.entry.SfDataPlaneLocatorBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sft.rev140701.Firewall;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sft.rev140701.ServiceFunctionTypeIdentity;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.VxlanGpe;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
.setServiceFunctionForwarder(new SffName(sffName));
}
- public ServiceFunctionBuilder serviceFunctionBuidler(ServiceFunctionBuilder serviceFunctionBuilder,
+ public ServiceFunctionBuilder serviceFunctionBuilder(ServiceFunctionBuilder serviceFunctionBuilder,
String ip, String sfName,
List<SfDataPlaneLocator> sfDataPlaneLocatorList,
Class<? extends ServiceFunctionTypeIdentity> type) {
List<ServiceFunction> serviceFunctionList) {
return serviceFunctionsBuilder.setServiceFunction(serviceFunctionList);
}
+
+ public ServiceFunctionBuilder serviceFunctionBuilder(String sfIp, int port, String sf1DplName,
+ String sffname, String sfName) {
+ SfDataPlaneLocatorBuilder sfDataPlaneLocator =
+ sfDataPlaneLocatorBuilder(new SfDataPlaneLocatorBuilder(), sfIp, port, sf1DplName, sffname);
+ List<SfDataPlaneLocator> sfDataPlaneLocatorList =
+ list(new ArrayList<SfDataPlaneLocator>(), sfDataPlaneLocator);
+ return serviceFunctionBuilder(
+ new ServiceFunctionBuilder(), sfIp, sfName, sfDataPlaneLocatorList, Firewall.class);
+ }
+
+
}
private TransactionInvoker txInvoker;
private Map<DatabaseSchema,TransactInvoker> transactInvokers;
private MonitorCallBack callback;
- // private ConnectionInfo key;
private InstanceIdentifier<Node> instanceIdentifier;
private volatile boolean hasDeviceOwnership = false;
private Entity connectedEntity;
return ovsdbConnectionInstance;
}
LOG.warn("OVSDB Connection Instance {} being replaced with client {}", key, externalClient);
- ovsdbConnectionInstance.disconnect();
// Unregister Cluster Ownership for ConnectionInfo
// Because the ovsdbConnectionInstance is about to be completely replaced!
unregisterEntityForOwnership(ovsdbConnectionInstance);
+ ovsdbConnectionInstance.disconnect();
+
removeConnectionInstance(key);
}
ConnectionInfo key = SouthboundMapper.createConnectionInfo(client);
OvsdbConnectionInstance ovsdbConnectionInstance = getConnectionInstance(key);
if (ovsdbConnectionInstance != null) {
+ // Unregister Entity ownership as soon as possible ,so this instance should
+ // not be used as a candidate in Entity election (given that this instance is
+ // about to disconnect as well), if current owner get disconnected from
+ // OVSDB device.
+ unregisterEntityForOwnership(ovsdbConnectionInstance);
+
txInvoker.invoke(new OvsdbNodeRemoveCommand(ovsdbConnectionInstance, null, null));
- removeConnectionInstance(key);
- // Unregister Cluster Onwership for ConnectionInfo
- unregisterEntityForOwnership(ovsdbConnectionInstance);
+ removeConnectionInstance(key);
} else {
- LOG.warn("OVSDB disconnected event did not find connection instance for {}", key);
+ LOG.warn("disconnected : Connection instance not found for OVSDB Node {} ", key);
}
LOG.trace("OvsdbConnectionManager: disconnected exit");
}
// Register Cluster Ownership for ConnectionInfo
registerEntityForOwnership(ovsdbConnectionInstance);
} else {
- LOG.warn("Failed to connect to Ovsdb Node {}", ovsdbNode.getConnectionInfo());
+ LOG.warn("Failed to connect to OVSDB Node {}", ovsdbNode.getConnectionInfo());
}
return client;
}
public void disconnect(OvsdbNodeAugmentation ovsdbNode) throws UnknownHostException {
OvsdbConnectionInstance client = getConnectionInstance(ovsdbNode.getConnectionInfo());
if (client != null) {
- client.disconnect();
-
// Unregister Cluster Onwership for ConnectionInfo
unregisterEntityForOwnership(client);
+ client.disconnect();
+
removeInstanceIdentifier(ovsdbNode.getConnectionInfo());
+ } else {
+ LOG.debug("disconnect : connection instance not found for {}",ovsdbNode.getConnectionInfo());
}
}
private void handleOwnershipChanged(EntityOwnershipChange ownershipChange) {
OvsdbConnectionInstance ovsdbConnectionInstance = getConnectionInstanceFromEntity(ownershipChange.getEntity());
- LOG.info("handleOwnershipChanged: {} event received for device {}",
+ LOG.debug("handleOwnershipChanged: {} event received for device {}",
ownershipChange, ovsdbConnectionInstance != null ? ovsdbConnectionInstance.getConnectionInfo()
- : "THAT'S NOT REGISTERED BY THIS SOUTHBOUND PLUGIN INSTANCE");
+ : "that's currently NOT registered by *this* southbound plugin instance");
if (ovsdbConnectionInstance == null) {
if (ownershipChange.isOwner()) {
- LOG.warn("handleOwnershipChanged: found no connection instance for {}", ownershipChange.getEntity());
+ LOG.warn("handleOwnershipChanged: *this* instance is elected as an owner of the device {} but it "
+ + "is NOT registered for ownership", ownershipChange.getEntity());
} else {
// EntityOwnershipService sends notification to all the nodes, irrespective of whether
// that instance registered for the device ownership or not. It is to make sure that
// If all the controller instance that was connected to the device are down, so the
// running instance can clear up the operational data store even though it was not
// connected to the device.
- LOG.debug("handleOwnershipChanged: found no connection instance for {}", ownershipChange.getEntity());
+ LOG.debug("handleOwnershipChanged: No connection instance found for {}", ownershipChange.getEntity());
}
// If entity has no owner, clean up the operational data store (it's possible because owner controller
// might went down abruptly and didn't get a chance to clean up the operational data store.
if (!ownershipChange.hasOwner()) {
- LOG.debug("{} has no onwer, cleaning up the operational data store", ownershipChange.getEntity());
- // Below code might look weird but it's required. We want to give first opportunity to the
- // previous owner of the device to clean up the operational data store if there is no owner now.
- // That way we will avoid lot of nasty md-sal exceptions because of concurrent delete.
- if (ownershipChange.wasOwner()) {
- cleanEntityOperationalData(ownershipChange.getEntity());
- }
- // If first cleanEntityOperationalData() was called, this call will be no-op.
+ LOG.info("{} has no owner, cleaning up the operational data store", ownershipChange.getEntity());
cleanEntityOperationalData(ownershipChange.getEntity());
}
return;
putConnectionInstance(ovsdbConnectionInstance.getMDConnectionInfo(),ovsdbConnectionInstance);
if (ownershipChange.isOwner() == ovsdbConnectionInstance.getHasDeviceOwnership()) {
- LOG.debug("handleOwnershipChanged: no change in ownership for {}. Ownership status is : {}",
- ovsdbConnectionInstance.getConnectionInfo(), ovsdbConnectionInstance.getHasDeviceOwnership());
+ LOG.info("handleOwnershipChanged: no change in ownership for {}. Ownership status is : {}",
+ ovsdbConnectionInstance.getConnectionInfo(), ovsdbConnectionInstance.getHasDeviceOwnership()
+ ? SouthboundConstants.OWNERSHIPSTATES.OWNER.getState()
+ : SouthboundConstants.OWNERSHIPSTATES.NONOWNER.getState());
return;
}
ovsdbConnectionInstance.setHasDeviceOwnership(ownershipChange.isOwner());
// You were not an owner, but now you are
if (ownershipChange.isOwner()) {
- LOG.info("handleOwnershipChanged: *this* southbound plugin instance is owner of device {}",
+ LOG.info("handleOwnershipChanged: *this* southbound plugin instance is an OWNER of the device {}",
ovsdbConnectionInstance.getConnectionInfo());
//*this* instance of southbound plugin is owner of the device,
//when clustering service implement a ownership grant strategy which can revoke the
//device ownership for load balancing the devices across the instances.
//Once this condition occur, we should unregister the callback.
- LOG.error("handleOwnershipChanged: *this* southbound plugin instance is no longer the owner of device {}",
+ LOG.error("handleOwnershipChanged: *this* southbound plugin instance is no longer the owner of device {}."
+ + "This should NOT happen.",
ovsdbConnectionInstance.getNodeId().getValue());
}
}
iid = SouthboundMapper.getInstanceIdentifier(openvswitchRow);
LOG.info("InstanceIdentifier {} generated for device "
+ "connection {}",iid,ovsdbConnectionInstance.getConnectionInfo());
-
+ ovsdbConnectionInstance.setInstanceIdentifier(iid);
}
YangInstanceIdentifier entityId = SouthboundUtil.getInstanceIdentifierCodec().getYangInstanceIdentifier(iid);
Entity deviceEntity = new Entity(ENTITY_TYPE, entityId);
EntityOwnershipCandidateRegistration registration =
entityOwnershipService.registerCandidate(candidateEntity);
ovsdbConnectionInstance.setDeviceOwnershipCandidateRegistration(registration);
- LOG.info("OVSDB entity {} is registred for ownership.", candidateEntity);
+ LOG.info("OVSDB entity {} is registered for ownership.", candidateEntity);
//If entity already has owner, it won't get notification from EntityOwnershipService
//so cache the connection instances.
if (ownershipStateOpt.isPresent()) {
EntityOwnershipState ownershipState = ownershipStateOpt.get();
if (ownershipState.hasOwner() && !ownershipState.isOwner()) {
- if (getConnectionInstance(ovsdbConnectionInstance.getMDConnectionInfo()) != null) {
- LOG.info("OVSDB entity {} is already owned by other southbound plugin "
- + "instance, so *this* instance is NOT an OWNER of the device",
- ovsdbConnectionInstance.getConnectionInfo());
- putConnectionInstance(ovsdbConnectionInstance.getMDConnectionInfo(),ovsdbConnectionInstance);
- }
+ LOG.info("OVSDB entity {} is already owned by other southbound plugin "
+ + "instance, so *this* instance is NOT an OWNER of the device",
+ ovsdbConnectionInstance.getConnectionInfo());
+ putConnectionInstance(ovsdbConnectionInstance.getMDConnectionInfo(),ovsdbConnectionInstance);
}
}
} catch (CandidateAlreadyRegisteredException e) {
- LOG.warn("OVSDB entity {} was already registered for {} ownership", candidateEntity, e);
+ LOG.warn("OVSDB entity {} was already registered for ownership", candidateEntity, e);
}
}
return this.mode;
}
}
+
+ public enum OWNERSHIPSTATES {
+ OWNER("OWNER"),
+ NONOWNER("NON-OWNER");
+
+ private final String state;
+
+ OWNERSHIPSTATES(String state) {
+ this.state = state;
+ }
+ @Override
+ public String toString() {
+ return state;
+ }
+
+ public String getState() {
+ return this.state;
+ }
+ }
}
try {
protocols = bridge.getProtocolsColumn().getData();
} catch (SchemaVersionMismatchException e) {
- LOG.warn("protocols not supported by this version of ovsdb", e);
+ // We don't care about the exception stack trace here
+ LOG.warn("protocols not supported by this version of ovsdb: {}", e.getMessage());
}
List<ProtocolEntry> protocolList = new ArrayList<>();
if (protocols != null && protocols.size() > 0) {
if (ownershipState.hasOwner() && !ownershipState.isOwner()) {
ovsdbConnection.registerConnectionListener(cm);
ovsdbConnection.startOvsdbManager(SouthboundConstants.DEFAULT_OVSDB_PORT);
+ LOG.info("*This* instance of OVSDB southbound provider is set as a SLAVE instance");
}
}
} catch (CandidateAlreadyRegisteredException e) {
entry.getKey().firstIdentifierOf(OvsdbBridgeAugmentation.class);
Optional<OvsdbBridgeAugmentation> bridgeOptional =
getOperationalState().getOvsdbBridgeAugmentation(bridgeIid);
- OvsdbBridgeAugmentation ovsdbBridge = null;
+ OvsdbBridgeAugmentation ovsdbBridge;
if (bridgeOptional.isPresent()) {
ovsdbBridge = bridgeOptional.get();
} else {
.where(bridge.getNameColumn().getSchema().opEqual(bridge.getNameColumn().getData()))
.build());
} catch (SchemaVersionMismatchException e) {
- LOG.warn("protocol not supported by this version of ovsdb", e);
+ // We don't care about the exception stack trace here
+ LOG.warn("protocol not supported by this version of ovsdb: {}", e.getMessage());
}
}
}
}
ovsdbNodeBuilder.setInterfaceTypeEntry(ifEntryList);
} catch (SchemaVersionMismatchException e) {
- LOG.debug("Iface types not supported by this version of ovsdb",e);
+ // We don't care about the exception stack trace here
+ LOG.debug("Iface types not supported by this version of ovsdb: {}", e.getMessage());
}
}
}
ovsdbNodeBuilder.setDatapathTypeEntry(dpEntryList);
} catch (SchemaVersionMismatchException e) {
- LOG.debug("Datapath types not supported by this version of ovsdb",e);
+ // We don't care about the exception stack trace here
+ LOG.debug("Datapath types not supported by this version of ovsdb: {}", e.getMessage());
}
}
}
}
} catch (SchemaVersionMismatchException e) {
- LOG.warn("protocol not supported by this version of ovsdb", e);
+ // We don't care about the exception stack trace here
+ LOG.warn("protocol not supported by this version of ovsdb: {}", e.getMessage());
}
return result;
}
getOvsdbConnectionInstance().getInstanceIdentifier());
} else {
LOG.debug("Other southbound plugin instances in cluster are connected to the device,"
- + " not deleting OvsdbNode form data store.");
+ + " not deleting OvsdbNode from operational data store.");
}
}
} catch (Exception e) {
if (connectedManager == 0) {
return true;
}
- }
- /*When switch is listening in passive mode, this number represent number of active connection to the device
- This is to handle the controller initiated connection scenario, where all the controller will connect, but
- switch will have only one manager.
- */
- if (onlyConnectedManager.getNumberOfConnections() > ONE_ACTIVE_CONNECTION_IN_PASSIVE_MODE) {
- return false;
+
+ /*When switch is listening in passive mode, this number represent number of active connection to the device
+ This is to handle the controller initiated connection scenario, where all the controller will connect, but
+ switch will have only one manager.
+ */
+ if (onlyConnectedManager.getNumberOfConnections() > ONE_ACTIVE_CONNECTION_IN_PASSIVE_MODE) {
+ return false;
+ }
}
return true;
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest()
+public class DataChangesManagedByOvsdbNodeEventTest {
+
+ @Mock private InstanceIdentifier<?> iid;
+ @Mock private AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event;
+ private Set<InstanceIdentifier<?>> removedPaths;
+ private DataChangesManagedByOvsdbNodeEvent dataChangesManagedByOvsdbNodeEvent;
+
+ @Before
+ public void setUp() throws Exception {
+ dataChangesManagedByOvsdbNodeEvent = mock(DataChangesManagedByOvsdbNodeEvent.class, Mockito.CALLS_REAL_METHODS);
+ MemberModifier.field(DataChangesManagedByOvsdbNodeEvent.class, "event").set(dataChangesManagedByOvsdbNodeEvent, event);
+ }
+
+ @Test
+ public void testDataChangesManagedByOvsdbNodeEvent() {
+ DataChangesManagedByOvsdbNodeEvent dataChangesManagedByOvsdbNodeEvent1 = new DataChangesManagedByOvsdbNodeEvent(iid, event);
+ assertEquals(iid, Whitebox.getInternalState(dataChangesManagedByOvsdbNodeEvent1, "iid"));
+ assertEquals(event, Whitebox.getInternalState(dataChangesManagedByOvsdbNodeEvent1, "event"));
+ }
+
+ @Test
+ public void testGetMethods() {
+ Map<InstanceIdentifier<?>,DataObject> data = new HashMap<>();
+ DataObject dataObject = mock(DataObject.class);
+
+ //Test getCreatedData()
+ when(event.getCreatedData()).thenReturn(data);
+ assertEquals(data, dataChangesManagedByOvsdbNodeEvent.getCreatedData());
+
+ //Test getUpdatedData()
+ when(event.getUpdatedData()).thenReturn(data);
+ assertEquals(data, dataChangesManagedByOvsdbNodeEvent.getUpdatedData());
+
+ //Test getOriginalData()
+ when(event.getOriginalData()).thenReturn(data);
+ assertEquals(data, dataChangesManagedByOvsdbNodeEvent.getOriginalData());
+
+ //Test getOriginalSubtree()
+ when(event.getOriginalSubtree()).thenReturn(dataObject);
+ assertEquals(dataObject, dataChangesManagedByOvsdbNodeEvent.getOriginalSubtree());
+
+ //Test getUpdatedSubtree()
+ when(event.getUpdatedSubtree()).thenReturn(dataObject);
+ assertEquals(dataObject, dataChangesManagedByOvsdbNodeEvent.getUpdatedSubtree());
+
+ //Test getRemovedPaths()
+ removedPaths = new HashSet<>();
+ when(event.getRemovedPaths()).thenReturn(removedPaths);
+ assertEquals(removedPaths, dataChangesManagedByOvsdbNodeEvent.getRemovedPaths());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.opendaylight.ovsdb.lib.notation.Column;
+import org.opendaylight.ovsdb.lib.notation.Mutator;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.operations.Insert;
+import org.opendaylight.ovsdb.lib.operations.Mutate;
+import org.opendaylight.ovsdb.lib.operations.Operation;
+import org.opendaylight.ovsdb.lib.operations.Operations;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.ColumnSchema;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TyperUtils.class, TransactUtils.class})
+public class OpenVSwitchBridgeAddCommandTest {
+ private OpenVSwitchBridgeAddCommand openVSwitchBridgeAddCommand;
+
+ @Before
+ public void setUp() {
+ openVSwitchBridgeAddCommand = mock(OpenVSwitchBridgeAddCommand.class, Mockito.CALLS_REAL_METHODS);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testExecute() throws Exception {
+ TransactionBuilder transaction = mock(TransactionBuilder.class);
+ List<Operation> operations = new ArrayList<>();
+ when(transaction.getOperations()).thenReturn(operations);
+
+ Bridge bridge = mock(Bridge.class);
+ when(transaction.getDatabaseSchema()).thenReturn(mock(DatabaseSchema.class));
+ PowerMockito.mockStatic(TyperUtils.class);
+ PowerMockito.when(TyperUtils.getTypedRowWrapper(any(DatabaseSchema.class), eq(Bridge.class))).thenReturn(bridge);
+
+ List<Insert> inserts = new ArrayList<>();
+ Insert insert = mock(Insert.class);
+ inserts.add(insert);
+ PowerMockito.mockStatic(TransactUtils.class);
+ when(bridge.getSchema()).thenReturn(mock(GenericTableSchema.class));
+ PowerMockito.when(TransactUtils.extractInsert(any(TransactionBuilder.class), any(GenericTableSchema.class))).thenReturn(inserts);
+
+ OpenVSwitch ovs = mock(OpenVSwitch.class);
+ PowerMockito.when(TyperUtils.getTypedRowWrapper(any(DatabaseSchema.class), eq(OpenVSwitch.class))).thenReturn(ovs);
+ PowerMockito.when(TransactUtils.extractNamedUuid(any(Insert.class))).thenReturn(mock(UUID.class));
+ doNothing().when(ovs).setBridges(any(Set.class));
+
+ Mutate<GenericTableSchema> mutate = mock(Mutate.class);
+ Operations op = (Operations) setField("op");
+ when(op.mutate(any(OpenVSwitch.class))).thenReturn(mutate);
+ Column<GenericTableSchema, Set<UUID>> column = mock(Column.class);
+ when(ovs.getBridgesColumn()).thenReturn(column);
+ when(column.getSchema()).thenReturn(mock(ColumnSchema.class));
+ when(column.getData()).thenReturn(new HashSet<UUID>());
+ when(mutate.addMutation(any(ColumnSchema.class), any(Mutator.class), any(Set.class))).thenReturn(mutate);
+ when(transaction.add(any(Operation.class))).thenReturn(transaction);
+
+ openVSwitchBridgeAddCommand.execute(transaction);
+ verify(transaction).add(any(Operation.class));
+ }
+
+ private Object setField(String fieldName) throws Exception {
+ Field field = Operations.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(field.get(Operations.class), mock(Operations.class));
+ return field.get(Operations.class);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.ovsdb.lib.notation.Column;
+import org.opendaylight.ovsdb.lib.operations.Mutate;
+import org.opendaylight.ovsdb.lib.operations.Operation;
+import org.opendaylight.ovsdb.lib.operations.Operations;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.ColumnSchema;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.api.support.membermodification.MemberMatcher;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.google.common.collect.ImmutableMap;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TransactUtils.class, TyperUtils.class, OvsdbNodeUpdateCommand.class, InstanceIdentifier.class})
+public class OvsdbNodeUpdateCommandTest {
+
+ private static final String EXTERNAL_ID_KEY = "external id key";
+ private static final String EXTERNAL_ID_VALUE = "external id value";
+ private static final String OTHER_CONFIG_KEY = "other config key";
+ private static final String OTHER_CONFIG_VALUE = "other config value";
+
+ @Mock private AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes;
+ private OvsdbNodeUpdateCommand ovsdbNodeUpdateCommand;
+
+ @Before
+ public void setUp() {
+ ovsdbNodeUpdateCommand = mock(OvsdbNodeUpdateCommand.class, Mockito.CALLS_REAL_METHODS);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testExecute() throws Exception {
+ TransactionBuilder transaction = mock(TransactionBuilder.class);
+ Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated = new HashMap<>();
+ InstanceIdentifier<OvsdbNodeAugmentation> iid = mock(InstanceIdentifier.class);
+ OvsdbNodeAugmentation ovsdbNode = mock(OvsdbNodeAugmentation.class);
+ updated.put(iid, ovsdbNode);
+ PowerMockito.mockStatic(TransactUtils.class);
+ PowerMockito.when(TransactUtils.extractCreatedOrUpdated(any(AsyncDataChangeEvent.class), eq(OvsdbNodeAugmentation.class))).thenReturn(updated);
+
+ ConnectionInfo connectionInfo = mock(ConnectionInfo.class);
+ when(ovsdbNode.getConnectionInfo()).thenReturn(connectionInfo);
+ when(connectionInfo.getRemoteIp()).thenReturn(mock(IpAddress.class));
+ when(connectionInfo.getRemotePort()).thenReturn(mock(PortNumber.class));
+
+ OpenVSwitch ovs = mock(OpenVSwitch.class);
+ when(transaction.getDatabaseSchema()).thenReturn(mock(DatabaseSchema.class));
+ PowerMockito.mockStatic(TyperUtils.class);
+ PowerMockito.when(TyperUtils.getTypedRowWrapper(any(DatabaseSchema.class), eq(OpenVSwitch.class))).thenReturn(ovs);
+
+ List<OpenvswitchExternalIds> externalIds = new ArrayList<>();
+ OpenvswitchExternalIds externalId = mock(OpenvswitchExternalIds.class);
+ externalIds.add(externalId);
+ when(externalId.getExternalIdKey()).thenReturn(EXTERNAL_ID_KEY);
+ when(externalId.getExternalIdValue()).thenReturn(EXTERNAL_ID_VALUE);
+ when(ovsdbNode.getOpenvswitchExternalIds()).thenReturn(externalIds);
+ PowerMockito.suppress(MemberMatcher.method(OvsdbNodeUpdateCommand.class, "stampInstanceIdentifier", TransactionBuilder.class, InstanceIdentifier.class));
+ PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(InstanceIdentifier.class));
+ doNothing().when(ovs).setExternalIds(any(ImmutableMap.class));
+
+ Mutate<GenericTableSchema> mutate = mock(Mutate.class);
+ Operations op = (Operations) setField("op");
+ Column<GenericTableSchema, Map<String, String>> column = mock(Column.class);
+ when(ovs.getExternalIdsColumn()).thenReturn(column);
+ when(column.getSchema()).thenReturn(mock(ColumnSchema.class));
+ when(column.getData()).thenReturn(new HashMap<String, String>());
+ when(op.mutate(any(OpenVSwitch.class))).thenReturn(mutate);
+ when(transaction.add(any(Operation.class))).thenReturn(transaction);
+
+ List<OpenvswitchOtherConfigs> otherConfigs = new ArrayList<>();
+ OpenvswitchOtherConfigs otherConfig = mock(OpenvswitchOtherConfigs.class);
+ otherConfigs.add(otherConfig);
+ when(ovsdbNode.getOpenvswitchOtherConfigs()).thenReturn(otherConfigs);
+ when(otherConfig.getOtherConfigKey()).thenReturn(OTHER_CONFIG_KEY);
+ when(otherConfig.getOtherConfigValue()).thenReturn(OTHER_CONFIG_VALUE);
+ doNothing().when(ovs).setOtherConfig(any(ImmutableMap.class));
+ when(ovs.getOtherConfigColumn()).thenReturn(column);
+
+ ovsdbNodeUpdateCommand.execute(transaction);
+ verify(externalId).getExternalIdKey();
+ verify(otherConfig).getOtherConfigKey();
+ verify(ovs, times(2)).getExternalIdsColumn();
+ verify(transaction, times(2)).add(any(Operation.class));
+ }
+
+ private Object setField(String fieldName) throws Exception {
+ Field field = Operations.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(field.get(Operations.class), mock(Operations.class));
+ return field.get(Operations.class);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.ovsdb.lib.notation.Column;
+import org.opendaylight.ovsdb.lib.notation.Condition;
+import org.opendaylight.ovsdb.lib.notation.Mutator;
+import org.opendaylight.ovsdb.lib.operations.Mutate;
+import org.opendaylight.ovsdb.lib.operations.Operation;
+import org.opendaylight.ovsdb.lib.operations.Operations;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.operations.Where;
+import org.opendaylight.ovsdb.lib.schema.ColumnSchema;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow10;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.api.support.membermodification.MemberMatcher;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import com.google.common.base.Optional;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({InstanceIdentifier.class, ProtocolUpdateCommand.class, TyperUtils.class})
+public class ProtocolUpdateCommandTest {
+ private static final String BRIDGE_NAME_COLUMN = null;
+ private Map<InstanceIdentifier<ProtocolEntry>, ProtocolEntry> protocols = new HashMap<>();
+ private ProtocolUpdateCommand protocolUpdateCommand;
+ @Mock private ProtocolEntry protocolEntry;
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() throws Exception {
+ protocolUpdateCommand = PowerMockito.mock(ProtocolUpdateCommand.class, Mockito.CALLS_REAL_METHODS);
+ protocols.put(mock(InstanceIdentifier.class), protocolEntry);
+ MemberModifier.field(ProtocolUpdateCommand.class, "protocols").set(protocolUpdateCommand, protocols);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testProtocolUpdateCommand() {
+ BridgeOperationalState state = mock(BridgeOperationalState.class);
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes = mock(AsyncDataChangeEvent.class);
+ ProtocolUpdateCommand protocolUpdateCommand1 = new ProtocolUpdateCommand(state, changes);
+ assertEquals(state, Whitebox.getInternalState(protocolUpdateCommand1, "operationalState"));
+ assertEquals(changes, Whitebox.getInternalState(protocolUpdateCommand1, "changes"));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testExecute() throws Exception {
+ TransactionBuilder transaction = mock(TransactionBuilder.class);
+
+ MemberModifier.suppress(MemberMatcher.method(ProtocolUpdateCommand.class, "getOperationalState"));
+ BridgeOperationalState bridgeOpState = mock(BridgeOperationalState.class);
+ when(protocolUpdateCommand.getOperationalState()).thenReturn(bridgeOpState);
+ Optional<ProtocolEntry> operationalProtocolEntryOptional = mock(Optional.class);
+ when(bridgeOpState.getProtocolEntry(any(InstanceIdentifier.class))).thenReturn(operationalProtocolEntryOptional);
+
+ when(operationalProtocolEntryOptional.isPresent()).thenReturn(false);
+ PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(InstanceIdentifier.class));
+
+ Optional<OvsdbBridgeAugmentation> bridgeOptional = mock(Optional.class);
+ when(bridgeOpState.getOvsdbBridgeAugmentation(any(InstanceIdentifier.class))).thenReturn(bridgeOptional);
+ OvsdbBridgeAugmentation ovsdbBridge= mock(OvsdbBridgeAugmentation.class);
+ when(bridgeOptional.isPresent()).thenReturn(true);
+ when(bridgeOptional.get()).thenReturn(ovsdbBridge);
+
+ OvsdbBridgeName ovsdbBridgeName = mock(OvsdbBridgeName.class);
+ when(ovsdbBridge.getBridgeName()).thenReturn(ovsdbBridgeName);
+ when(protocolEntry.getProtocol()).thenAnswer(new Answer<Class<? extends OvsdbBridgeProtocolBase>>() {
+ public Class<? extends OvsdbBridgeProtocolBase> answer(
+ InvocationOnMock invocation) throws Throwable {
+ return OvsdbBridgeProtocolOpenflow10.class;
+ }
+ });
+
+ Bridge bridge= mock(Bridge.class);
+ PowerMockito.mockStatic(TyperUtils.class);
+ when(transaction.getDatabaseSchema()).thenReturn(mock(DatabaseSchema.class));
+ when(TyperUtils.getTypedRowWrapper(any(DatabaseSchema.class), eq(Bridge.class))).thenReturn(bridge);
+ doNothing().when(bridge).setName(anyString());
+ doNothing().when(bridge).setProtocols(any(Set.class));
+
+ Operations op = (Operations) setField("op");
+ Mutate<GenericTableSchema> mutate = mock(Mutate.class);
+ when(op.mutate(any(Bridge.class))).thenReturn(mutate);
+ Column<GenericTableSchema, Set<String>> column = mock(Column.class);
+ when(bridge.getProtocolsColumn()).thenReturn(column);
+ when(column.getSchema()).thenReturn(mock(ColumnSchema.class));
+ when(column.getData()).thenReturn(new HashSet<String>());
+ when(mutate.addMutation(any(ColumnSchema.class), any(Mutator.class), any(Set.class))).thenReturn(mutate);
+
+ Column<GenericTableSchema, String> nameColumn = mock(Column.class);
+ when(bridge.getNameColumn()).thenReturn(nameColumn);
+ when(nameColumn.getData()).thenReturn(BRIDGE_NAME_COLUMN);
+ ColumnSchema<GenericTableSchema, String> columnSchema = mock(ColumnSchema.class);
+ when(nameColumn.getSchema()).thenReturn(columnSchema);
+ when(columnSchema.opEqual(anyString())).thenReturn(mock(Condition.class));
+ Where where = mock(Where.class);
+ when(mutate.where(any(Condition.class))).thenReturn(where);
+ when(where.build()).thenReturn(mock(Operation.class));
+ when(transaction.add(any(Operation.class))).thenReturn(transaction);
+
+ protocolUpdateCommand.execute(transaction);
+ verify(transaction).add(any(Operation.class));
+ }
+
+ private Object setField(String fieldName) throws Exception {
+ Field field = Operations.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(field.get(Operations.class), mock(Operations.class));
+ return field.get(Operations.class);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TransactUtils.class, TerminationPointDeleteCommand.class, TyperUtils.class})
+public class TerminationPointDeleteCommandTest {
+
+ private TerminationPointDeleteCommand terminationPointDeleteCommand;
+ @Mock private BridgeOperationalState state;
+ @Mock private AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes;
+ private Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation> originals = new HashMap<>();
+ private Map<InstanceIdentifier<Node>, Node> originalNodes = new HashMap<>();
+ private Set<InstanceIdentifier<OvsdbTerminationPointAugmentation>> removedTps = new HashSet<>();
+
+ @Before
+ public void setUp() throws Exception {
+ terminationPointDeleteCommand = mock(TerminationPointDeleteCommand.class, Mockito.CALLS_REAL_METHODS);
+ MemberModifier.field(TerminationPointDeleteCommand.class, "operationalState").set(terminationPointDeleteCommand, state);
+ MemberModifier.field(TerminationPointDeleteCommand.class, "changes").set(terminationPointDeleteCommand, changes);
+ }
+
+ @Test
+ public void testExecute() {
+ TransactionBuilder transaction = mock(TransactionBuilder.class);
+ PowerMockito.mockStatic(TransactUtils.class);
+ when(TransactUtils.extractOriginal(changes, OvsdbTerminationPointAugmentation.class)).thenReturn(originals);
+ when(TransactUtils.extractOriginal(changes, Node.class)).thenReturn(originalNodes);
+ when(TransactUtils.extractRemoved(changes, OvsdbTerminationPointAugmentation.class)).thenReturn(removedTps);
+ terminationPointDeleteCommand.execute(transaction);
+ verify(terminationPointDeleteCommand, times(3)).getChanges();
+ }
+}
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._4.grouping.NxSetNshc4Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.SrcChoice;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpShaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc1CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc2CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIdCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIpv4DstCaseBuilder;
public static Action nxMoveRegTunIdAction(Class<? extends NxmNxReg> src,
boolean groupBucket) {
- return nxMoveRegAction(new SrcNxRegCaseBuilder()
- .setNxReg(src).build(),
- new DstNxTunIdCaseBuilder()
- .setNxTunId(Boolean.TRUE).build(),
+ return nxMoveRegAction(new SrcNxRegCaseBuilder().setNxReg(src).build(),
+ new DstNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(),
31,
groupBucket);
}
public static Action nxMoveArpShaToArpThaAction() {
- return nxMoveRegAction(new SrcNxArpShaCaseBuilder()
- .setNxArpSha(Boolean.TRUE).build(),
- new DstNxArpThaCaseBuilder()
- .setNxArpTha(Boolean.TRUE).build(),
+ return nxMoveRegAction(new SrcNxArpShaCaseBuilder().setNxArpSha(Boolean.TRUE).build(),
+ new DstNxArpThaCaseBuilder().setNxArpTha(Boolean.TRUE).build(),
47, false);
}
public static Action nxMoveEthSrcToEthDstAction() {
- return nxMoveRegAction(new SrcOfEthSrcCaseBuilder()
- .setOfEthSrc(Boolean.TRUE).build(),
- new DstOfEthDstCaseBuilder()
- .setOfEthDst(Boolean.TRUE).build(),
+ return nxMoveRegAction(new SrcOfEthSrcCaseBuilder().setOfEthSrc(Boolean.TRUE).build(),
+ new DstOfEthDstCaseBuilder().setOfEthDst(Boolean.TRUE).build(),
47, false);
}
public static Action nxMoveArpSpaToArpTpaAction() {
- return nxMoveRegAction(new SrcOfArpSpaCaseBuilder()
- .setOfArpSpa(Boolean.TRUE).build(),
- new DstOfArpTpaCaseBuilder()
- .setOfArpTpa(Boolean.TRUE).build());
+ return nxMoveRegAction(new SrcOfArpSpaCaseBuilder().setOfArpSpa(Boolean.TRUE).build(),
+ new DstOfArpTpaCaseBuilder().setOfArpTpa(Boolean.TRUE).build());
}
public static Action nxOutputRegAction(SrcChoice srcChoice) {
}
public static Action nxMoveRegTunDstToNshc1() {
- return nxMoveRegAction(new SrcNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),
- new DstNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(), 31, false);
+ return nxMoveRegAction(
+ new SrcNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),
+ new DstNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),
+ 31, false);
}
public static Action nxMoveTunIdtoNshc2() {
- return nxMoveRegAction(new SrcNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(),
- new DstNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(), 31, false);
+ return nxMoveRegAction(
+ new SrcNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(),
+ new DstNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),
+ 31, false);
+ }
+
+ public static Action nxMoveNshc1ToTunIpv4Dst() {
+ return nxMoveRegAction(
+ new SrcNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),
+ new DstNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),
+ 31, false);
+ }
+
+ public static Action nxMoveNshc2ToTunId() {
+ return nxMoveRegAction(
+ new SrcNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),
+ new DstNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(),
+ 31, false);
}
public static Action nxLoadTunIdAction(BigInteger tunnelId, boolean groupBucket) {
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FlowUtils {
private static final Logger LOG = LoggerFactory.getLogger(FlowUtils.class);
private static final String OPENFLOW = "openflow";
+ public final static long REG_VALUE_FROM_LOCAL = 0x1L;
+ public final static long REG_VALUE_FROM_REMOTE = 0x2L;
+ public static final Class<? extends NxmNxReg> REG_FIELD = NxmNxReg0.class;
public static String getNodeName(long dpidLong) {
return OPENFLOW + ":" + dpidLong;
return new NodeConnectorId(nodeName + ":" + ofPort);
}
+ public static NodeConnectorId getSpecialNodeConnectorId(long dpidLong, String portName) {
+ return new NodeConnectorId(getNodeName(dpidLong) + ":" + portName);
+ }
+
public static NodeConnectorId getNodeConnectorId(long dpidLong, long ofPort) {
return getNodeConnectorId(ofPort, getNodeName(dpidLong));
}
LOG.error(e.getMessage(), e);
}
- LOG.info("Cannot find data for Flow {}", flowBuilder.getFlowName());
+ LOG.info("Cannot find data for Flow {} in {}", flowBuilder.getFlowName(), store);
return null;
}
}
/**
- * Create NORMAL Reserved Port Instruction (packet_in)
+ * Create LOCAL Reserved Port Instruction
*
* @param nodeName Uri Prefix, containing nodeConnectorType and dpId (aka NodeId)
* @param ib Map InstructionBuilder without any instructions
return ib;
}
+ /**
+ * Create NORMAL Reserved Port Instruction (packet_in)
+ *
+ * @param ib Map InstructionBuilder without any instructions
+ * @param dpidLong Long the datapath ID of a switch/node
+ * @return ib Map InstructionBuilder with instructions
+ */
+ public static InstructionBuilder createLocalInstructions(InstructionBuilder ib, long dpidLong) {
+ List<Action> actionList = new ArrayList<>();
+ ActionBuilder ab = new ActionBuilder();
+
+ OutputActionBuilder output = new OutputActionBuilder();
+ output.setOutputNodeConnector(new NodeConnectorId("openflow:" + dpidLong + ":"
+ + OutputPortValues.LOCAL.toString()));
+ ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ actionList.add(ab.build());
+
+ // Create an Apply Action
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ // Wrap our Apply Action in an Instruction
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+ return ib;
+ }
+
/**
* Create Output Port Instruction
*
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.ovsdb.southbound.SouthboundConstants;
import org.opendaylight.ovsdb.southbound.SouthboundMapper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final String DEFAULT_OPENFLOW_PORT = "6653";
private static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
private MdsalUtils mdsalUtils;
+ public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
public SouthboundUtils(MdsalUtils mdsalUtils) {
this.mdsalUtils = mdsalUtils;
}
+ public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
+ = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
+ .put("internal", InterfaceTypeInternal.class)
+ .put("vxlan", InterfaceTypeVxlan.class)
+ .put("patch", InterfaceTypePatch.class)
+ .put("system", InterfaceTypeSystem.class)
+ .put("tap", InterfaceTypeTap.class)
+ .put("geneve", InterfaceTypeGeneve.class)
+ .put("gre", InterfaceTypeGre.class)
+ .put("ipsec_gre", InterfaceTypeIpsecGre.class)
+ .put("gre64", InterfaceTypeGre64.class)
+ .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
+ .put("lisp", InterfaceTypeLisp.class)
+ .put("dpdk", InterfaceTypeDpdk.class)
+ .put("dpdkr", InterfaceTypeDpdkr.class)
+ .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
+ .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
+ .build();
+
public NodeId createNodeId(IpAddress ip, PortNumber port) {
String uriString = SouthboundConstants.OVSDB_URI_PREFIX + "://"
+ new String(ip.getValue()) + ":" + port.getValue();
return SouthboundMapper.createInstanceIdentifier(createManagedNodeId(key, bridgeName));
}
+ public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName){
+
+ InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
+ .create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
+ .child(Node.class,node.getKey())
+ .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
+
+ LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
+ return terminationPointPath;
+ }
+
public NodeKey createNodeKey(IpAddress ip, PortNumber port) {
return new NodeKey(createNodeId(ip, port));
}
InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
}
+
+ public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
+ String type, Map<String, String> options,
+ Map<String, String> externalIds) {
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+
+ tpAugmentationBuilder.setName(portName);
+ if (type != null) {
+ tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
+ }
+
+ if (options != null && options.size() > 0) {
+ List<Options> optionsList = new ArrayList<>();
+ for (Map.Entry<String, String> entry : options.entrySet()) {
+ OptionsBuilder optionsBuilder = new OptionsBuilder();
+ optionsBuilder.setKey(new OptionsKey(entry.getKey()));
+ optionsBuilder.setOption(entry.getKey());
+ optionsBuilder.setValue(entry.getValue());
+ optionsList.add(optionsBuilder.build());
+ }
+ tpAugmentationBuilder.setOptions(optionsList);
+ }
+
+ if (externalIds != null && externalIds.size() > 0) {
+ List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
+ for (Map.Entry<String, String> entry : externalIds.entrySet()) {
+ InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
+ interfaceExternalIdsBuilder.setKey(new InterfaceExternalIdsKey(entry.getKey()));
+ interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
+ interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
+ externalIdsList.add(interfaceExternalIdsBuilder.build());
+ }
+ tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
+ }
+
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+ /* TODO SB_MIGRATION should this be merge or mdsalUtils.put */
+ return mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
+ }
+
+ public TerminationPoint readTerminationPoint(Node bridgeNode, String bridgeName, String portName) {
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
+ bridgeNode, portName);
+ return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpIid);
+ }
+
+ public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
+ return addTerminationPoint(bridgeNode, bridgeName, portName, type, null, null);
+ }
+
+ public Boolean addTunnelTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type,
+ Map<String, String> options) {
+ return addTerminationPoint(bridgeNode, bridgeName, portName, type, options, null);
+ }
}