<!-- openflowplugin -->
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>openflowplugin</artifactId>
+ <artifactId>openflowplugin-api</artifactId>
<version>${openflowplugin.distribution.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>openflowplugin-api</artifactId>
+ <artifactId>openflowplugin-extension-api</artifactId>
+ <version>${openflowplugin.distribution.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-extension-nicira</artifactId>
+ <version>${openflowplugin.distribution.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowjava-extension-nicira-api</artifactId>
+ <version>${openflowplugin.distribution.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowjava-extension-nicira</artifactId>
+ <version>${openflowplugin.distribution.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin</artifactId>
<version>${openflowplugin.distribution.version}</version>
</dependency>
<exclude>opendaylight/plugins/org.opendaylight.controller.thirdparty.org.openflow.openflowj-*.jar</exclude>
<exclude>opendaylight/plugins/org.opendaylight.controller.protocol_plugins.openflow-*.jar</exclude>
<exclude>opendaylight/plugins/org.opendaylight.controller.samples.*.jar</exclude>
+ <exclude>opendaylight/plugins/org.opendaylight.controller.md.statistics-manager*.jar</exclude>
<exclude>opendaylight/configuration/initial/*toaster*.xml</exclude>
</excludes>
</fileSet>
<name>openflow-switch-connection-provider-default-impl</name>
<port>6633</port>
<switch-idle-timeout>15000</switch-idle-timeout>
+<!-- Exemplary TLS configuration:
+ - uncomment the <tls> tag
+ - copy exemplary-switch-privkey.pem, exemplary-switch-cert.pem and exemplary-cacert.pem
+ files into your virtual machine
+ - set VM encryption options to use copied keys
+ - start communication
+ Please visit OpenflowPlugin or Openflow Protocol Library#Documentation wiki pages
+ for detailed information regarding TLS -->
+<!-- <tls>
+ <keystore>/exemplary-ctlKeystore</keystore>
+ <keystore-type>JKS</keystore-type>
+ <keystore-path-type>CLASSPATH</keystore-path-type>
+ <keystore-password>opendaylight</keystore-password>
+ <truststore>/exemplary-ctlTrustStore</truststore>
+ <truststore-type>JKS</truststore-type>
+ <truststore-path-type>CLASSPATH</truststore-path-type>
+ <truststore-password>opendaylight</truststore-password>
+ <certificate-password>opendaylight</certificate-password>
+ </tls> -->
</module>
<!-- default OF-switch-connection-provider (port 6653) -->
<module>
<name>openflow-switch-connection-provider-legacy-impl</name>
<port>6653</port>
<switch-idle-timeout>15000</switch-idle-timeout>
+<!-- Exemplary TLS configuration:
+ - uncomment the <tls> tag
+ - copy exemplary-switch-privkey.pem, exemplary-switch-cert.pem and exemplary-cacert.pem
+ files into your virtual machine
+ - set VM encryption options to use copied keys
+ - start communication
+ Please visit OpenflowPlugin or Openflow Protocol Library#Documentation wiki pages
+ for detailed information regarding TLS -->
+<!-- <tls>
+ <keystore>/exemplary-ctlKeystore</keystore>
+ <keystore-type>JKS</keystore-type>
+ <keystore-path-type>CLASSPATH</keystore-path-type>
+ <keystore-password>opendaylight</keystore-password>
+ <truststore>/exemplary-ctlTrustStore</truststore>
+ <truststore-type>JKS</truststore-type>
+ <truststore-path-type>CLASSPATH</truststore-path-type>
+ <truststore-password>opendaylight</truststore-password>
+ <certificate-password>opendaylight</certificate-password>
+ </tls> -->
</module>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:openflowplugin:ofjava:nx:api:config?module=openflowjava-nx-api-config&revision=2014-07-11</capability>
+ </required-capabilities>
+
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflowplugin:ofjava:nx:api:config">prefix:openflowjava-extension-nicira-api</type>
+ <name>openflowjava-extension-nx-api-bundle</name>
+ <openflow-switch-connection-provider>
+ <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
+ <name>openflow-switch-connection-provider-legacy</name>
+ </openflow-switch-connection-provider>
+ <openflow-switch-connection-provider>
+ <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
+ <name>openflow-switch-connection-provider-default</name>
+ </openflow-switch-connection-provider>
+ </module>
+ </modules>
+
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflowplugin:ofjava:nx:api:config">prefix:nicira-extension-codec-registrator</type>
+ <instance>
+ <name>openflowjava-nicira-ext-registrator</name>
+ <provider>/modules/module[type='openflowjava-extension-nicira-api'][name='openflowjava-extension-nx-api-bundle']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+
+ </configuration>
+</snapshot>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+
+This program and the accompanying materials are made available under the
+terms of the Eclipse Public License v1.0 which accompanies this distribution,
+and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:openflowplugin:nx:config:impl?module=nicira-extension-impl&revision=2014-07-11</capability>
+ <!-- openflowplugin -->
+ <capability>urn:opendaylight:params:xml:ns:yang:openflow:common:config?module=openflow-provider&revision=2014-03-26</capability>
+ </required-capabilities>
+
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflowplugin:nx:config:impl">prefix:nicira-extension-provider-impl</type>
+ <name>nicira-extension-provider-default-impl</name>
+
+ <openflow-plugin-provider>
+ <type xmlns:opfprov="urn:opendaylight:params:xml:ns:yang:openflow:common:config">opfprov:openflow-provider</type>
+ <name>openflow-provider</name>
+ </openflow-plugin-provider>
+ </module>
+ </modules>
+ </data>
+
+ </configuration>
+</snapshot>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:openflowplugin:ofjava:nx:config?module=openflowjava-nx-config&revision=2014-07-11</capability>
+ </required-capabilities>
+
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflowplugin:ofjava:nx:config">prefix:openflowjava-extension-nicira</type>
+ <name>openflow-nx-bundle</name>
+ <nicira-extension-codec-registrator>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflowplugin:ofjava:nx:api:config">prefix:nicira-extension-codec-registrator</type>
+ <name>openflowjava-nicira-ext-registrator</name>
+ </nicira-extension-codec-registrator>
+ </module>
+ </modules>
+ </data>
+
+ </configuration>
+</snapshot>
<packaging>bundle</packaging>
<properties>
- <sal.version>1.1-SNAPSHOT</sal.version>
- <yangtools.binding.version>0.6.2-SNAPSHOT</yangtools.binding.version>
- <yangtools.generator.version>0.6.2-SNAPSHOT</yangtools.generator.version>
- <yangtools.version>0.6.2-SNAPSHOT</yangtools.version>
+ <openflowplugin-nicira.version>0.0.3-SNAPSHOT</openflowplugin-nicira.version>
</properties>
<dependencies>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-inventory</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-extension-nicira</artifactId>
+ <version>${openflowplugin-nicira.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowjava-extension-nicira</artifactId>
+ <version>${openflowplugin-nicira.version}</version>
+ </dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
@Immutable
public class EpKey {
+ @Override
+ public String toString() {
+ return "EpKey [l2Context=" + l2Context + ", macAddress=" + macAddress +
+ "]";
+ }
+
final L2ContextId l2Context;
final MacAddress macAddress;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.DestinationMapper;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.GroupTable;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OfTable;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OfTable.OfTableCtx;
import org.opendaylight.groupbasedpolicy.resolver.PolicyScope;
import org.opendaylight.groupbasedpolicy.util.SetUtils;
import org.opendaylight.groupbasedpolicy.util.SingletonTask;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig.LearningMode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
/**
* Manage policies on switches by subscribing to updates from the
private static final Logger LOG =
LoggerFactory.getLogger(PolicyManager.class);
- private final DataBroker dataBroker;
private final SwitchManager switchManager;
private final PolicyResolver policyResolver;
RpcProviderRegistry rpcRegistry,
ScheduledExecutorService executor) {
super();
- this.dataBroker = dataBroker;
this.switchManager = switchManager;
this.executor = executor;
this.policyResolver = policyResolver;
this, policyResolver, switchManager,
endpointManager, executor);
flowPipeline = ImmutableList.of(new PortSecurity(ctx),
+ new GroupTable(ctx),
new SourceMapper(ctx),
new DestinationMapper(ctx),
- new PolicyEnforcer(ctx),
- new GroupTable(ctx));
+ new PolicyEnforcer(ctx));
policyScope = policyResolver.registerListener(this);
if (switchManager != null)
* @param cg the {@link ConditionGroup}
* @return the unique ID
*/
- public int getConfGroupOrdinal(final ConditionGroup cg) {
+ public int getCondGroupOrdinal(final ConditionGroup cg) {
if (cg == null) return 0;
Integer ord = cgOrdinals.get(cg);
if (ord == null) {
table.update(nodeId, info, dirty);
} catch (Exception e) {
LOG.error("Failed to write flow table {}",
- table.getClass().getName(), e);
+ table.getClass().getSimpleName(), e);
}
}
return null;
private void updateSwitchConfig(NodeId nodeId, OfOverlayNodeConfig config) {
SwitchState state = getSwitchState(nodeId);
state.setConfig(config);
- notifySwitchUpdated(nodeId);
+ notifySwitchUpdated(nodeId);
}
private void notifySwitchUpdated(NodeId nodeId) {
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+
+import java.util.Comparator;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Ordering;
+
+public class ActionComparator implements Comparator<Action> {
+ public static final ActionComparator INSTANCE = new ActionComparator();
+
+ @Override
+ public int compare(Action arg0, Action arg1) {
+ return ComparisonChain.start()
+ .compare(arg0.getOrder(), arg1.getOrder(),
+ Ordering.natural().nullsLast())
+ .result();
+ }
+
+}
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
import org.opendaylight.groupbasedpolicy.resolver.EgKey;
+import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
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.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
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.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Sets;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
+
/**
* Manage the table that maps the destination address to the next hop
* for the path as well as applies any relevant routing transformations.
*/
public static final MacAddress ROUTER_MAC =
new MacAddress("88:f0:31:b5:12:b5");
+ public static final MacAddress MULTICAST_MAC =
+ new MacAddress("01:00:00:00:00:00");
public DestinationMapper(OfTable.OfTableCtx ctx) {
super(ctx);
dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
HashSet<EgKey> visitedEgs = new HashSet<>();
+ HashSet<Integer> visitedFds = new HashSet<>();
+
for (EgKey epg : ctx.epManager.getGroupsForNode(nodeId)) {
Set<EgKey> peers = Sets.union(Collections.singleton(epg),
policyInfo.getPeers(epg));
for (EgKey peer : peers) {
syncEPG(t, tiid, flowMap, nodeId,
- policyInfo, peer, visitedEgs);
+ policyInfo, peer,
+ visitedEgs, visitedFds);
}
}
}
Map<String, FlowCtx> flowMap,
NodeId nodeId, PolicyInfo policyInfo,
EgKey key,
- HashSet<EgKey> visitedEgs) throws Exception {
+ HashSet<EgKey> visitedEgs,
+ HashSet<Integer> visitedFds) throws Exception {
if (visitedEgs.contains(key)) return;
visitedEgs.add(key);
+ IndexedTenant tenant = ctx.policyResolver.getTenant(key.getTenantId());
+ EndpointGroup eg = tenant.getEndpointGroup(key.getEgId());
+ L2FloodDomain fd = tenant.resolveL2FloodDomain(eg.getNetworkDomain());
+ Subnet sn = tenant.resolveSubnet(eg.getNetworkDomain());
+ L3Context l3c = tenant.resolveL3Context(eg.getNetworkDomain());
+ int l3Id = 0;
+
+ if (l3c != null)
+ l3Id = ctx.policyManager.getContextOrdinal(key.getTenantId(),
+ l3c.getId());
+
Collection<Endpoint> egEps = ctx.epManager
.getEndpointsForGroup(key);
+
for (Endpoint e : egEps) {
if (e.getTenant() == null || e.getEndpointGroup() == null)
continue;
OfOverlayContext ofc = e.getAugmentation(OfOverlayContext.class);
if (ofc == null || ofc.getNodeId() == null) continue;
- syncEP(t, tiid, flowMap, nodeId, policyInfo, e, ofc, key);
+ syncEP(t, tiid, flowMap, nodeId, policyInfo, e, ofc, tenant, key);
+ }
+
+ if (fd == null) return;
+ Integer fdId = ctx.policyManager.getContextOrdinal(key.getTenantId(),
+ fd.getId());
+ if (visitedFds.contains(fdId)) return;
+ visitedFds.add(fdId);
+
+ FlowId flowId = new FlowId(new StringBuilder()
+ .append("broadcast|")
+ .append(fdId).toString());
+ if (visit(flowMap, flowId.getValue())) {
+ MatchBuilder mb = new MatchBuilder()
+ .setEthernetMatch(new EthernetMatchBuilder()
+ .setEthernetDestination(new EthernetDestinationBuilder()
+ .setAddress(MULTICAST_MAC)
+ .setMask(MULTICAST_MAC)
+ .build())
+ .build());
+ addNxRegMatch(mb, RegMatch.of(NxmNxReg5.class,Long.valueOf(fdId)));
+
+ FlowBuilder flow = base()
+ .setPriority(Integer.valueOf(140))
+ .setId(flowId)
+ .setMatch(mb.build())
+ .setInstructions(instructions(applyActionIns(nxMoveRegTunIdAction(NxmNxReg0.class, false),
+ groupAction(Long.valueOf(fdId)))));
+ writeFlow(t, tiid, flow.build());
+ }
+
+ if (sn != null && sn.getVirtualRouterIp() != null) {
+ if (sn.getVirtualRouterIp().getIpv4Address() != null) {
+ String ikey = sn.getVirtualRouterIp().getIpv4Address().getValue();
+ flowId = new FlowId(new StringBuffer()
+ .append("routerarp|")
+ .append(sn.getId().getValue())
+ .append("|")
+ .append(ikey)
+ .append("|")
+ .append(l3Id)
+ .toString());
+ if (visit(flowMap, flowId.getValue())) {
+ MatchBuilder mb = new MatchBuilder()
+ .setEthernetMatch(ethernetMatch(null, null, ARP))
+ .setLayer3Match(new ArpMatchBuilder()
+ .setArpOp(Integer.valueOf(1))
+ .setArpTargetTransportAddress(new Ipv4Prefix(ikey))
+ .build());
+ addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class,
+ Long.valueOf(l3Id)));
+ BigInteger routerMac =
+ new BigInteger(1, HexEncode
+ .bytesFromHexString(ROUTER_MAC
+ .getValue()));
+ /* XXX - TODO add output to inport action */
+ FlowBuilder flowb = base()
+ .setPriority(150)
+ .setId(flowId)
+ .setMatch(mb.build())
+ .setInstructions(instructions(applyActionIns(nxMoveEthSrcToEthDstAction(),
+ setDlSrcAction(ROUTER_MAC),
+ nxLoadArpOpAction(BigInteger.valueOf(2L)),
+ nxMoveArpShaToArpThaAction(),
+ nxLoadArpShaAction(routerMac),
+ nxMoveArpSpaToArpTpaAction(),
+ nxLoadArpSpaAction(ikey),
+ outputAction(new NodeConnectorId(nodeId.getValue() + ":INPORT")))));
+ writeFlow(t, tiid, flowb.build());
+ }
+ } else {
+ LOG.warn("IPv6 virtual router {} for subnet {} not supported",
+ sn.getVirtualRouterIp(), sn.getId().getValue());
+ }
}
}
Map<String, FlowCtx> flowMap,
NodeId nodeId, PolicyInfo policyInfo,
Endpoint e, OfOverlayContext ofc,
- EgKey key)
+ IndexedTenant tenant, EgKey key)
throws Exception {
-
ArrayList<Instruction> instructions = new ArrayList<>();
ArrayList<Instruction> l3instructions = new ArrayList<>();
+ List<Action> applyActions = new ArrayList<>();
+ List<Action> l3ApplyActions = new ArrayList<>();
+
int order = 0;
+ EndpointGroup eg = tenant.getEndpointGroup(e.getEndpointGroup());
+ L3Context l3c = tenant.resolveL3Context(eg.getNetworkDomain());
+ L2BridgeDomain bd = tenant.resolveL2BridgeDomain(eg.getNetworkDomain());
+
+ int egId = 0, bdId = 0, l3Id = 0, cgId = 0;
+
+ egId = ctx.policyManager.getContextOrdinal(e.getTenant(),
+ e.getEndpointGroup());
+ if (bd != null)
+ bdId = ctx.policyManager.getContextOrdinal(e.getTenant(),
+ bd.getId());
+ if (l3c != null)
+ l3Id = ctx.policyManager.getContextOrdinal(e.getTenant(),
+ l3c.getId());
+ List<ConditionName> conds = ctx.epManager.getCondsForEndpoint(e);
+ ConditionGroup cg =
+ policyInfo.getEgCondGroup(new EgKey(e.getTenant(),
+ e.getEndpointGroup()),
+ conds);
+ cgId = ctx.policyManager.getCondGroupOrdinal(cg);
+ Action setdEPG = nxLoadRegAction(NxmNxReg2.class,
+ BigInteger.valueOf(egId));
+ Action setdCG = nxLoadRegAction(NxmNxReg3.class,
+ BigInteger.valueOf(cgId));
+ Action setNextHop;
String nextHop;
if (LocationType.External.equals(ofc.getLocationType())) {
// XXX - TODO - perform NAT and send to the external network
nextHop = "external";
LOG.warn("External endpoints not yet supported");
return;
- } else {
- Action setDlSrc = FlowUtils.setDlSrc(ROUTER_MAC);
- Action setDlDst = FlowUtils.setDlDst(e.getMacAddress());
- Action decTtl = FlowUtils.decNwTtl();
+ } else {
+ Action setDlSrc = setDlSrcAction(ROUTER_MAC);
+ Action decTtl = decNwTtlAction();
if (Objects.equals(ofc.getNodeId(), nodeId)) {
- // this is a local endpoint
+ // this is a local endpoint; send to the approppriate local
+ // port
nextHop = ofc.getNodeConnectorId().getValue();
- // XXX - TODO - instead of outputting, write next hop
- // to a register and output from the policy table
- Action output = FlowUtils.outputAction(ofc.getNodeConnectorId());
+ long portNum;
+ try {
+ portNum = getOfPortNum(ofc.getNodeConnectorId());
+ } catch (NumberFormatException ex) {
+ LOG.warn("Could not parse port number {}",
+ ofc.getNodeConnectorId(), ex);
+ return;
+ }
+
+ setNextHop = nxLoadRegAction(NxmNxReg7.class,
+ BigInteger.valueOf(portNum));
- instructions.add(new InstructionBuilder()
- .setOrder(order)
- .setInstruction(FlowUtils.writeActionIns(output))
- .build());
- l3instructions.add(new InstructionBuilder()
- .setOrder(order)
- .setInstruction(FlowUtils.writeActionIns(setDlSrc,
- setDlDst,
- decTtl,
- output))
- .build());
+ Action setDlDst = setDlDstAction(e.getMacAddress());
+ l3ApplyActions.add(setDlSrc);
+ l3ApplyActions.add(setDlDst);
+ l3ApplyActions.add(decTtl);
order +=1;
} else {
// this endpoint is on a different switch; send to the
if (tunDst == null) return;
if (tunPort == null) return;
+ Action tundstAction;
+
if (tunDst.getIpv4Address() != null) {
nextHop = tunDst.getIpv4Address().getValue();
-
- // XXX - TODO Add action: set tunnel dst to tunDst ipv4
+ tundstAction = nxLoadTunIPv4Action(nextHop, false);
} else if (tunDst.getIpv6Address() != null) {
- nextHop = tunDst.getIpv6Address().getValue();
-
- // XXX - TODO Add action: set tunnel dst to tunDst ipv6
+ // nextHop = tunDst.getIpv6Address().getValue();
+ LOG.error("IPv6 tunnel destination {} for {} not supported",
+ tunDst.getIpv6Address().getValue(),
+ ofc.getNodeId());
+ return;
} else {
// this shouldn't happen
LOG.error("Tunnel IP for {} invalid", ofc.getNodeId());
return;
}
- Action output = FlowUtils.outputAction(tunPort);
+
+ long portNum;
+ try {
+ portNum = getOfPortNum(tunPort);
+ } catch (NumberFormatException ex) {
+ LOG.warn("Could not parse port number {}",
+ ofc.getNodeConnectorId(), ex);
+ return;
+ }
- // XXX - TODO Add action: set tunnel_id from sEPG register
- instructions.add(new InstructionBuilder()
- .setOrder(order)
- .setInstruction(FlowUtils.writeActionIns(output))
- .build());
- l3instructions.add(new InstructionBuilder()
- .setOrder(order)
- .setInstruction(FlowUtils.writeActionIns(setDlSrc,
- decTtl,
- output))
- .build());
+ setNextHop = nxLoadRegAction(NxmNxReg7.class,
+ BigInteger.valueOf(portNum));
+ Action tunIdAction =
+ nxMoveRegTunIdAction(NxmNxReg0.class, false);
+ applyActions.add(tunIdAction);
+ applyActions.add(tundstAction);
+ l3ApplyActions.add(setDlSrc);
+ l3ApplyActions.add(decTtl);
order +=1;
}
}
+ applyActions.add(setdEPG);
+ applyActions.add(setdCG);
+ applyActions.add(setNextHop);
+ Instruction applyActionsIns = new InstructionBuilder()
+ .setOrder(order++)
+ .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+ .build();
+ instructions.add(applyActionsIns);
+
+ applyActions.addAll(l3ApplyActions);
+ applyActionsIns = new InstructionBuilder()
+ .setOrder(order++)
+ .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+ .build();
+ l3instructions.add(applyActionsIns);
- int egId = ctx.policyManager.getContextOrdinal(e.getTenant(),
- e.getEndpointGroup());
- List<ConditionName> conds = ctx.epManager.getCondsForEndpoint(e);
- ConditionGroup cg =
- policyInfo.getEgCondGroup(new EgKey(e.getTenant(),
- e.getEndpointGroup()),
- conds);
- int cgId = ctx.policyManager.getConfGroupOrdinal(cg);
-
- // XXX TODO - add action set dEPG and dCG into registers
Instruction gotoTable = new InstructionBuilder()
.setOrder(order++)
- .setInstruction(FlowUtils.gotoTableIns((short)(getTableId()+1)))
+ .setInstruction(gotoTableIns((short)(getTableId()+1)))
.build();
instructions.add(gotoTable);
l3instructions.add(gotoTable);
FlowId flowid = new FlowId(new StringBuilder()
- .append(e.getL2Context().getValue())
+ .append(bdId)
.append("|l2|")
.append(e.getMacAddress().getValue())
.append("|")
.append(nextHop)
.toString());
if (visit(flowMap, flowid.getValue())) {
- LOG.info("{} deg:{} dcg:{}", e.getMacAddress(), egId, cgId);
- // XXX TODO add match against bridge domain register
+ MatchBuilder mb = new MatchBuilder()
+ .setEthernetMatch(ethernetMatch(null,
+ e.getMacAddress(),
+ null));
+ addNxRegMatch(mb, RegMatch.of(NxmNxReg4.class, Long.valueOf(bdId)));
FlowBuilder flowb = base()
.setId(flowid)
.setPriority(Integer.valueOf(50))
- .setMatch(new MatchBuilder()
- .setEthernetMatch(FlowUtils.ethernetMatch(null,
- e.getMacAddress(),
- null))
- .build())
+ .setMatch(mb.build())
.setInstructions(new InstructionsBuilder()
.setInstruction(instructions)
.build());
String ikey = null;
if (l3a.getIpAddress().getIpv4Address() != null) {
ikey = l3a.getIpAddress().getIpv4Address().getValue();
- etherType = FlowUtils.IPv4;
+ etherType = IPv4;
m = new Ipv4MatchBuilder()
.setIpv4Destination(new Ipv4Prefix(ikey))
.build();
} else if (l3a.getIpAddress().getIpv6Address() != null) {
ikey = l3a.getIpAddress().getIpv6Address().getValue();
- etherType = FlowUtils.IPv6;
+ etherType = IPv6;
m = new Ipv6MatchBuilder()
.setIpv6Destination(new Ipv6Prefix(ikey))
.build();
.append(nextHop)
.toString());
if (visit(flowMap, flowid.getValue())) {
- // XXX TODO add match against routing domain register
-
+ MatchBuilder mb = new MatchBuilder()
+ .setEthernetMatch(ethernetMatch(null,
+ ROUTER_MAC,
+ etherType))
+ .setLayer3Match(m);
+ addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class,
+ Long.valueOf(l3Id)));
FlowBuilder flowb = base()
.setId(flowid)
.setPriority(Integer.valueOf(132))
- .setMatch(new MatchBuilder()
- .setEthernetMatch(FlowUtils.ethernetMatch(null,
- ROUTER_MAC,
- etherType))
- .setLayer3Match(m)
- .build())
+ .setMatch(mb.build())
.setInstructions(new InstructionsBuilder()
.setInstruction(l3instructions)
.build());
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
/**
* Base class for managing flow tables
}
}
- ListenableFuture<Void> result = t.submit();
- Futures.addCallback(result, updateCallback);
+ t.submit().get();
+ //ListenableFuture<Void> result = t.submit();
+ //Futures.addCallback(result, updateCallback);
}
// *********
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+import java.math.BigInteger;
import java.util.ArrayList;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
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;
+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.GoToTableCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCaseBuilder;
+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.instruction.go.to.table._case.GoToTableBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+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.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.ExtensionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.DstChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpShaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpThaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIpv4DstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpOpCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpSpaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpTpaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfEthDstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegMoveNodesNodeGroupBucketsBucketActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionOutputRegNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegMoveNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputRegBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoadBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.nx.reg.load.DstBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMove;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMoveBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.SrcBuilder;
+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.SrcNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfArpSpaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfEthSrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg0Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg1Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg2Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg3Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg4Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg5Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg6Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg7Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxTunIdKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.reg.grouping.NxmNxRegBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.tun.id.grouping.NxmNxTunIdBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import com.google.common.collect.ImmutableList;
+import com.google.common.net.InetAddresses;
/**
* Utilities for constructing OpenFlow flows
.build())
.build();
}
-
- public static Instruction outputActionIns(NodeConnectorId id) {
- return writeActionIns(outputAction(id));
- }
- public static ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> writeActionList(Action... actions) {
+ public static ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList(Action... actions) {
ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> alist
= new ArrayList<>();
int count = 0;
}
return alist;
}
-
- public static Instruction writeActionIns(Action... actions) {
- return new WriteActionsCaseBuilder()
- .setWriteActions(new WriteActionsBuilder()
- .setAction(writeActionList(actions))
+ public static Instruction applyActionIns(Action... actions) {
+ return new ApplyActionsCaseBuilder()
+ .setApplyActions(new ApplyActionsBuilder()
+ .setAction(actionList(actions))
.build())
.build();
}
-
+ public static Instructions instructions(Instruction... instructions) {
+ ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> ins
+ = new ArrayList<>();
+ int order = 0;
+ for (Instruction i : instructions) {
+ ins.add(new InstructionBuilder()
+ .setOrder(order++)
+ .setInstruction(i)
+ .build());
+ }
+ return new InstructionsBuilder().setInstruction(ins).build();
+ }
+
public static Instructions dropInstructions() {
- return new InstructionsBuilder()
- .setInstruction(ImmutableList.of(new InstructionBuilder()
- .setOrder(Integer.valueOf(0))
- .setInstruction(new WriteActionsCaseBuilder()
- .setWriteActions(new WriteActionsBuilder()
- .setAction(ImmutableList.of(new ActionBuilder()
- .setOrder(Integer.valueOf(0))
- .setAction(dropAction())
- .build()))
- .build())
- .build())
- .build()))
- .build();
+ return instructions(applyActionIns(dropAction()));
}
public static Action dropAction() {
.build();
}
- public static Action setDlSrc(MacAddress mac) {
+ public static Action groupAction(Long id) {
+ return new GroupActionCaseBuilder()
+ .setGroupAction(new GroupActionBuilder()
+ .setGroupId(id)
+ .build())
+ .build();
+ }
+
+ public static Action setDlSrcAction(MacAddress mac) {
return new SetDlSrcActionCaseBuilder()
.setSetDlSrcAction(new SetDlSrcActionBuilder()
.setAddress(mac)
.build();
}
- public static Action setDlDst(MacAddress mac) {
+ public static Action setDlDstAction(MacAddress mac) {
return new SetDlDstActionCaseBuilder()
.setSetDlDstAction(new SetDlDstActionBuilder()
.setAddress(mac)
.build();
}
- public static Action decNwTtl() {
+ public static Action decNwTtlAction() {
return new DecNwTtlCaseBuilder()
.setDecNwTtl(new DecNwTtlBuilder()
.build())
.build();
}
+ public static Action nxLoadRegAction(DstChoice dstChoice,
+ BigInteger value,
+ int endOffset,
+ boolean groupBucket) {
+ NxRegLoad r = new NxRegLoadBuilder()
+ .setDst(new DstBuilder()
+ .setDstChoice(dstChoice)
+ .setStart(Integer.valueOf(0))
+ .setEnd(Integer.valueOf(endOffset))
+ .build())
+ .setValue(value)
+ .build();
+ if (groupBucket) {
+ return new NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder()
+ .setNxRegLoad(r).build();
+ } else {
+ return new NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder()
+ .setNxRegLoad(r).build();
+ }
+ }
+
+ public static Action nxLoadRegAction(DstChoice dstChoice,
+ BigInteger value) {
+ return nxLoadRegAction(dstChoice, value, 31, false);
+ }
+
+ public static Action nxLoadRegAction(Class<? extends NxmNxReg> reg,
+ BigInteger value) {
+ return nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(reg).build(),
+ value);
+ }
+ public static Action nxLoadTunIPv4Action(String ipAddress,
+ boolean groupBucket) {
+ int ip = InetAddresses.coerceToInteger(InetAddresses.forString(ipAddress));
+ long ipl = ip & 0xffffffffL;
+ return nxLoadRegAction(new DstNxTunIpv4DstCaseBuilder()
+ .setNxTunIpv4Dst(Boolean.TRUE).build(),
+ BigInteger.valueOf(ipl),
+ 31,
+ groupBucket);
+ }
+
+ public static Action nxLoadArpOpAction(BigInteger value) {
+ return nxLoadRegAction(new DstOfArpOpCaseBuilder()
+ .setOfArpOp(Boolean.TRUE).build(), value, 15, false);
+ }
+
+ public static Action nxLoadArpShaAction(BigInteger value) {
+ return nxLoadRegAction(new DstNxArpShaCaseBuilder()
+ .setNxArpSha(Boolean.TRUE).build(), value, 47, false);
+ }
+
+ public static Action nxLoadArpSpaAction(BigInteger value) {
+ return nxLoadRegAction(new DstOfArpSpaCaseBuilder()
+ .setOfArpSpa(Boolean.TRUE).build(), value);
+ }
+
+ public static Action nxLoadArpSpaAction(String ipAddress) {
+ int ip = InetAddresses.coerceToInteger(InetAddresses.forString(ipAddress));
+ long ipl = ip & 0xffffffffL;
+ return nxLoadArpSpaAction(BigInteger.valueOf(ipl));
+ }
+
+ public static Action nxMoveRegAction(SrcChoice srcChoice,
+ DstChoice dstChoice,
+ int endOffset,
+ boolean groupBucket) {
+ NxRegMove r = new NxRegMoveBuilder()
+ .setSrc(new SrcBuilder()
+ .setSrcChoice(srcChoice)
+ .setStart(Integer.valueOf(0))
+ .setEnd(Integer.valueOf(endOffset))
+ .build())
+ .setDst(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.DstBuilder()
+ .setDstChoice(dstChoice)
+ .setStart(Integer.valueOf(0))
+ .setEnd(Integer.valueOf(endOffset))
+ .build())
+ .build();
+ if (groupBucket) {
+ return new NxActionRegMoveNodesNodeGroupBucketsBucketActionsCaseBuilder()
+ .setNxRegMove(r).build();
+ } else {
+ return new NxActionRegMoveNodesNodeTableFlowApplyActionsCaseBuilder()
+ .setNxRegMove(r).build();
+ }
+ }
+
+ public static Action nxMoveRegAction(SrcChoice srcChoice,
+ DstChoice dstChoice) {
+ return nxMoveRegAction(srcChoice, dstChoice, 31, false);
+ }
+
+ public static Action nxMoveRegTunIdAction(Class<? extends NxmNxReg> src,
+ boolean groupBucket) {
+ 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(),
+ 47, false);
+ }
+
+ public static Action nxMoveEthSrcToEthDstAction() {
+ 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());
+ }
+
+ public static Action nxOutputRegAction(SrcChoice srcChoice) {
+ NxOutputReg r = new NxOutputRegBuilder()
+ .setSrc(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.nx.output.reg.SrcBuilder()
+ .setSrcChoice(srcChoice)
+ .setOfsNbits(Integer.valueOf(31))
+ .build())
+ .setMaxLen(Integer.valueOf(0xffff))
+ .build();
+ return new NxActionOutputRegNodesNodeTableFlowApplyActionsCaseBuilder()
+ .setNxOutputReg(r).build();
+ }
+
+ public static Action nxOutputRegAction(Class<? extends NxmNxReg> reg) {
+ return nxOutputRegAction(new SrcNxRegCaseBuilder().setNxReg(reg).build());
+ }
+
+ public static class RegMatch {
+ final Class<? extends NxmNxReg> reg;
+ final Long value;
+ public RegMatch(Class<? extends NxmNxReg> reg, Long value) {
+ super();
+ this.reg = reg;
+ this.value = value;
+ }
+ public static RegMatch of(Class<? extends NxmNxReg> reg, Long value) {
+ return new RegMatch(reg, value);
+ }
+ }
+
+ public static void addNxRegMatch(MatchBuilder match,
+ RegMatch... matches) {
+ ArrayList<ExtensionList> extensions = new ArrayList<>();
+ for (RegMatch rm : matches) {
+ Class<? extends ExtensionKey> key;
+ if (NxmNxReg0.class.equals(rm.reg)) {
+ key = NxmNxReg0Key.class;
+ } else if (NxmNxReg1.class.equals(rm.reg)) {
+ key = NxmNxReg1Key.class;
+ } else if (NxmNxReg2.class.equals(rm.reg)) {
+ key = NxmNxReg2Key.class;
+ } else if (NxmNxReg3.class.equals(rm.reg)) {
+ key = NxmNxReg3Key.class;
+ } else if (NxmNxReg4.class.equals(rm.reg)) {
+ key = NxmNxReg4Key.class;
+ } else if (NxmNxReg5.class.equals(rm.reg)) {
+ key = NxmNxReg5Key.class;
+ } else if (NxmNxReg6.class.equals(rm.reg)) {
+ key = NxmNxReg6Key.class;
+ } else {
+ key = NxmNxReg7Key.class;
+ }
+ NxAugMatchNodesNodeTableFlow am =
+ new NxAugMatchNodesNodeTableFlowBuilder()
+ .setNxmNxReg(new NxmNxRegBuilder()
+ .setReg(rm.reg)
+ .setValue(rm.value)
+ .build())
+ .build();
+ extensions.add(new ExtensionListBuilder()
+ .setExtensionKey(key)
+ .setExtension(new ExtensionBuilder()
+ .addAugmentation(NxAugMatchNodesNodeTableFlow.class, am)
+ .build())
+ .build());
+ }
+ GeneralAugMatchNodesNodeTableFlow m =
+ new GeneralAugMatchNodesNodeTableFlowBuilder()
+ .setExtensionList(extensions)
+ .build();
+ match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
+ }
+
+ public static void addNxTunIdMatch(MatchBuilder match,
+ int tunId) {
+ NxAugMatchNodesNodeTableFlow am =
+ new NxAugMatchNodesNodeTableFlowBuilder()
+ .setNxmNxTunId(new NxmNxTunIdBuilder()
+ .setValue(BigInteger.valueOf(tunId))
+ .build())
+ .build();
+ GeneralAugMatchNodesNodeTableFlow m =
+ new GeneralAugMatchNodesNodeTableFlowBuilder()
+ .setExtensionList(ImmutableList.of(new ExtensionListBuilder()
+ .setExtensionKey(NxmNxTunIdKey.class)
+ .setExtension(new ExtensionBuilder()
+ .addAugmentation(NxAugMatchNodesNodeTableFlow.class, am)
+ .build())
+ .build()))
+ .build();
+ match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
+ }
+
public static EthernetMatch ethernetMatch(MacAddress srcMac,
MacAddress dstMac,
Long etherType) {
import com.google.common.base.Objects;
import com.google.common.base.Optional;
-import com.google.common.util.concurrent.Futures;
+import com.google.common.collect.Ordering;
+
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
/**
* Manage the group tables for handling broadcast/multicast
public GroupTable(OfTableCtx ctx) {
super(ctx);
- // TODO Auto-generated constructor stub
}
@Override
// Since this is happening concurrently with other things that are
// working in subtrees of nodes, we have to do two transactions
ReadOnlyTransaction t = ctx.dataBroker.newReadOnlyTransaction();
- InstanceIdentifier<Node> niid =
- FlowUtils.createNodePath(nodeId);
+ InstanceIdentifier<Node> niid = createNodePath(nodeId);
Optional<Node> r =
t.read(LogicalDatastoreType.CONFIGURATION, niid).get();
if (!r.isPresent()) return;
}
sync(nodeId, policyInfo, dirty, groupMap);
-
+
WriteTransaction wt = ctx.dataBroker.newWriteOnlyTransaction();
+ boolean wrote = syncGroupToStore(wt, nodeId, groupMap);
+ if (wrote)
+ wt.submit().get();
+ }
+
+ protected boolean syncGroupToStore(WriteTransaction wt,
+ NodeId nodeId,
+ HashMap<GroupId, GroupCtx> groupMap) {
boolean wrote = false;
for (GroupCtx gctx : groupMap.values()) {
InstanceIdentifier<Group> giid =
- FlowUtils.createGroupPath(nodeId, gctx.groupId);
+ createGroupPath(nodeId, gctx.groupId);
if (!gctx.visited) {
// Remove group table
wrote = true;
if (bctx.b != null) bid = bctx.b.getBucketId();
else bid = bctx.newb.getBucketId();
InstanceIdentifier<Bucket> biid =
- FlowUtils.createBucketPath(nodeId,
- gctx.groupId,
- bid);
+ createBucketPath(nodeId,
+ gctx.groupId,
+ bid);
if (!bctx.visited) {
// remove bucket
- LOG.info("delete {} {}", gctx.groupId, bid);
wrote = true;
wt.delete(LogicalDatastoreType.CONFIGURATION, biid);
- } else if (bctx.b == null ||
- !Objects.equal(bctx.newb,
- bctx.b)) {
+ } else if (bctx.b == null) {
+ // new bucket
+ buckets.add(bctx.newb);
+ } else if (!Objects.equal(bctx.newb.getAction(),
+ Ordering.from(ActionComparator.INSTANCE)
+ .sortedCopy(bctx.b.getAction()))) {
// update bucket
buckets.add(bctx.newb);
- LOG.info("{} {}", gctx.groupId, bctx.newb.getBucketId());
- }
- if (buckets.size() > 0) {
- GroupBuilder gb = new GroupBuilder()
- .setGroupId(gctx.groupId)
- .setGroupType(GroupTypes.GroupAll)
- .setBuckets(new BucketsBuilder()
- .setBucket(buckets)
- .build());
- wrote = true;
- wt.merge(LogicalDatastoreType.CONFIGURATION,
- giid, gb.build());
}
}
+ if (buckets.size() > 0) {
+ GroupBuilder gb = new GroupBuilder()
+ .setGroupId(gctx.groupId)
+ .setGroupType(GroupTypes.GroupAll)
+ .setBuckets(new BucketsBuilder()
+ .setBucket(buckets)
+ .build());
+ wrote = true;
+ wt.merge(LogicalDatastoreType.CONFIGURATION,
+ giid, gb.build());
+ }
}
}
- if (wrote)
- Futures.addCallback(wt.submit(), updateCallback);
+ return wrote;
}
protected void sync(NodeId nodeId, PolicyInfo policyInfo, Dirty dirty,
// we'll use the fdId with the high bit set for remote bucket
// and just the local port number for local bucket
for (NodeId destNode : ctx.epManager.getNodesForGroup(epg)) {
+ if (nodeId.equals(destNode)) continue;
+
long bucketId = (long)ctx.policyManager
.getContextOrdinal(destNode.getValue());
bucketId |= 1L << 31;
NodeConnectorId tunPort =
ctx.switchManager.getTunnelPort(nodeId);
if (tunDst == null || tunPort == null) continue;
+ Action tundstAction = null;
if (tunDst.getIpv4Address() != null) {
- // XXX - TODO Add action: set tunnel dst to tunDst ipv4
- } else if (tunDst.getIpv6Address() != null) {
- // XXX - TODO Add action: set tunnel dst to tunDst ipv6
+ String nextHop = tunDst.getIpv4Address().getValue();
+ tundstAction = nxLoadTunIPv4Action(nextHop, true);
+ } else {
+ LOG.error("IPv6 tunnel destination {} for {} not supported",
+ tunDst.getIpv6Address().getValue(),
+ destNode);
+ continue;
}
- int epgId = ctx.policyManager
- .getContextOrdinal(epg.getTenantId(),
- epg.getEgId());
-
- // TODO add action: set tunnel ID to epgId
-
- Action output = FlowUtils.outputAction(tunPort);
-
BucketBuilder bb = new BucketBuilder()
.setBucketId(new BucketId(Long.valueOf(bucketId)))
- .setAction(FlowUtils.writeActionList(output));
+ .setAction(actionList(tundstAction,
+ outputAction(tunPort)));
updateBucket(gctx, bb);
}
for (Endpoint localEp : ctx.epManager.getEPsForNode(nodeId, epg)) {
if (ofc == null || ofc.getNodeConnectorId() == null ||
(LocationType.External.equals(ofc.getLocationType())))
continue;
- String cnid = ofc.getNodeConnectorId().getValue();
- int ci = cnid.lastIndexOf(':');
- if (ci < 0 || (ci+1 >= cnid.length()))
- continue;
+
long bucketId;
try {
- bucketId = Long.parseLong(cnid.substring(ci+1));
+ bucketId = getOfPortNum(ofc.getNodeConnectorId());
} catch (NumberFormatException e) {
- LOG.warn("Could not parse port number {}", cnid);
+ LOG.warn("Could not parse port number {}",
+ ofc.getNodeConnectorId(), e);
continue;
}
- Action output = FlowUtils.outputAction(ofc.getNodeConnectorId());
-
+ Action output = outputAction(ofc.getNodeConnectorId());
BucketBuilder bb = new BucketBuilder()
.setBucketId(new BucketId(Long.valueOf(bucketId)))
- .setAction(FlowUtils.writeActionList(output));
+ .setAction(actionList(output));
updateBucket(gctx, bb);
}
}
bctx.newb = bb.build();
}
- private static class BucketCtx {
+ protected static class BucketCtx {
Bucket b;
Bucket newb;
boolean visited = false;
}
}
- private static class GroupCtx {
+ protected static class GroupCtx {
GroupId groupId;
Map<BucketId, BucketCtx> bucketMap = new HashMap<>();
boolean visited = false;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.SwitchManager;
import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.util.concurrent.FutureCallback;
-
/**
* Manage the state of a openflow table by reacting to any events and updating
* the table state. This is an abstract class that must be extended for
// Utility methods
// ***************
-
/**
- * Generic callback for handling result of flow manipulation
- * @author readams
- *
- * @param <T> the expected output type
+ * Parse an OF port number from a node connector ID
+ * @param id the ID
+ * @return the port number
*/
- protected static class OfCallback<T> implements FutureCallback<T> {
- @Override
- public void onSuccess(T result) {
- }
-
- @Override
- public void onFailure(Throwable t) {
- LOG.error("Failed to add flow entry", t);
- }
+ protected static long getOfPortNum(NodeConnectorId id) {
+ String cnid = id.getValue();
+ int ci = cnid.lastIndexOf(':');
+ if (ci < 0 || (ci+1 >= cnid.length()))
+ throw new NumberFormatException("Invalid node connector ID " + cnid);
+ return Long.parseLong(cnid.substring(ci+1));
}
- protected static final OfCallback<Void> updateCallback =
- new OfCallback<>();
-
-
}
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Classifier;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
+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.openflowjava.nx.match.rev140421.NxmNxReg0;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
+
/**
* Manage the table that enforces policy on the traffic. Traffic is denied
* unless specifically allowed by policy
PolicyInfo policyInfo, Dirty dirty)
throws Exception {
dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
+ allowFromTunnel(t, tiid, flowMap, nodeId);
HashSet<CgPair> visitedPairs = new HashSet<>();
List<ConditionName> conds =
ctx.epManager.getCondsForEndpoint(src);
ConditionGroup scg = policyInfo.getEgCondGroup(sepg, conds);
- int scgId = ctx.policyManager.getConfGroupOrdinal(scg);
+ int scgId = ctx.policyManager.getCondGroupOrdinal(scg);
Set<EgKey> peers = policyInfo.getPeers(sepg);
for (EgKey depg : peers) {
policyInfo.getEgCondGroup(new EgKey(dst.getTenant(),
dst.getEndpointGroup()),
conds);
- int dcgId = ctx.policyManager.getConfGroupOrdinal(dcg);
+ int dcgId = ctx.policyManager.getCondGroupOrdinal(dcg);
CgPair p = new CgPair(depgId, sepgId, dcgId, scgId);
if (visitedPairs.contains(p)) continue;
.append("intraallow|")
.append(sepgId).toString());
if (visit(flowMap, flowId.getValue())) {
- // XXX - TODO - add match against sepg, depg registers
- // XXX - TOOD - add output action from destination register
+ MatchBuilder mb = new MatchBuilder();
+ addNxRegMatch(mb,
+ RegMatch.of(NxmNxReg0.class,Long.valueOf(sepgId)),
+ RegMatch.of(NxmNxReg2.class,Long.valueOf(sepgId)));
+ FlowBuilder flow = base()
+ .setId(flowId)
+ .setMatch(mb.build())
+ .setPriority(65000)
+ .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
+ writeFlow(t, tiid, flow.build());
+ }
+ }
+
+ private void allowFromTunnel(ReadWriteTransaction t,
+ InstanceIdentifier<Table> tiid,
+ Map<String, FlowCtx> flowMap, NodeId nodeId) {
+ NodeConnectorId tunPort =
+ ctx.switchManager.getTunnelPort(nodeId);
+ if (tunPort == null) return;
+
+ FlowId flowId = new FlowId("tunnelallow");
+ if (visit(flowMap, flowId.getValue())) {
+ MatchBuilder mb = new MatchBuilder()
+ .setInPort(tunPort);
+ addNxRegMatch(mb,
+ RegMatch.of(NxmNxReg1.class,Long.valueOf(0xffffff)));
FlowBuilder flow = base()
.setId(flowId)
- .setPriority(65000);
+ .setMatch(mb.build())
+ .setPriority(65000)
+ .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
writeFlow(t, tiid, flow.build());
}
}
MatchBuilder baseMatch = new MatchBuilder();
- if (d.equals(Direction.Out)) {
+ if (d.equals(Direction.In)) {
idb.append(p.sepg)
.append("|")
.append(p.scgId)
.append(p.dcgId)
.append("|")
.append(priority);
- // XXX - TODO - add match against sepg, depg, scg, and dcg
- // registers
+ addNxRegMatch(baseMatch,
+ RegMatch.of(NxmNxReg0.class,Long.valueOf(p.sepg)),
+ RegMatch.of(NxmNxReg1.class,Long.valueOf(p.scgId)),
+ RegMatch.of(NxmNxReg2.class,Long.valueOf(p.depg)),
+ RegMatch.of(NxmNxReg3.class,Long.valueOf(p.dcgId)));
} else {
idb.append(p.depg)
.append("|")
.append(p.scgId)
.append("|")
.append(priority);
- // XXX - TODO - add match against sepg, depg, scg, and dcg
- // registers
+ addNxRegMatch(baseMatch,
+ RegMatch.of(NxmNxReg0.class,Long.valueOf(p.depg)),
+ RegMatch.of(NxmNxReg1.class,Long.valueOf(p.dcgId)),
+ RegMatch.of(NxmNxReg2.class,Long.valueOf(p.sepg)),
+ RegMatch.of(NxmNxReg3.class,Long.valueOf(p.scgId)));
}
for (MatchBuilder match : matches) {
Match m = match.build();
FlowId flowId = new FlowId(baseId + "|" + m.toString());
- flow.setMatch(m)
- .setId(flowId)
- .setPriority(Integer.valueOf(priority));
if (visit(flowMap, flowId.getValue())) {
- LOG.info("{} {} {} {}", p.sepg, p.scgId, p.depg, p.dcgId);
+ flow.setMatch(m)
+ .setId(flowId)
+ .setPriority(Integer.valueOf(priority))
+ .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
writeFlow(t, tiid, flow.build());
}
}
Endpoint e, OfOverlayContext ofc,
Integer priority) {
FlowId flowid = new FlowId(new StringBuilder()
- .append(ofc.getNodeConnectorId())
+ .append(ofc.getNodeConnectorId().getValue())
.append("|")
.append(e.getMacAddress().getValue())
.toString());
continue;
}
FlowId flowid = new FlowId(new StringBuilder()
- .append(ofc.getNodeConnectorId())
+ .append(ofc.getNodeConnectorId().getValue())
.append("|")
.append(e.getMacAddress().getValue())
.append("|")
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import org.opendaylight.groupbasedpolicy.resolver.EgKey;
import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
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;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
+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.openflowjava.nx.match.rev140421.NxmNxReg0;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
+
/**
* Manage the table that assigns source endpoint group, bridge domain, and
* router domain to registers to be used by other tables.
Dirty dirty) throws Exception {
dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
- // XXX TODO Set sEPG from tunnel ports using the tunnel ID
-
for (EgKey sepg : ctx.epManager.getGroupsForNode(nodeId)) {
+ IndexedTenant tenant =
+ ctx.policyResolver.getTenant(sepg.getTenantId());
+ if (tenant == null) continue;
+
+ EndpointGroup eg = tenant.getEndpointGroup(sepg.getEgId());
+ L3Context l3c = tenant.resolveL3Context(eg.getNetworkDomain());
+ L2BridgeDomain bd = tenant.resolveL2BridgeDomain(eg.getNetworkDomain());
+ L2FloodDomain fd = tenant.resolveL2FloodDomain(eg.getNetworkDomain());
+ int egId = 0, bdId = 0, fdId = 0, l3Id = 0;
+
+ egId = ctx.policyManager.getContextOrdinal(sepg.getTenantId(),
+ sepg.getEgId());
+ if (bd != null)
+ bdId = ctx.policyManager.getContextOrdinal(sepg.getTenantId(),
+ bd.getId());
+ if (fd != null)
+ fdId = ctx.policyManager.getContextOrdinal(sepg.getTenantId(),
+ fd.getId());
+ if (l3c != null)
+ l3Id = ctx.policyManager.getContextOrdinal(sepg.getTenantId(),
+ l3c.getId());
+
+ NodeConnectorId tunPort =
+ ctx.switchManager.getTunnelPort(nodeId);
+ if (tunPort != null) {
+ FlowId flowid = new FlowId(new StringBuilder()
+ .append(tunPort.getValue())
+ .append("|tunnel|")
+ .append(egId)
+ .append("|")
+ .append(bdId)
+ .append("|")
+ .append(fdId)
+ .append("|")
+ .append(l3Id)
+ .toString());
+ if (visit(flowMap, flowid.getValue())) {
+ MatchBuilder mb = new MatchBuilder()
+ .setInPort(tunPort);
+ addNxTunIdMatch(mb, egId);
+ Action segReg = nxLoadRegAction(NxmNxReg0.class,
+ BigInteger.valueOf(egId));
+ // set condition group register to all ones to bypass
+ // policy enforcement
+ Action scgReg = nxLoadRegAction(NxmNxReg1.class,
+ BigInteger.valueOf(0xffffff));
+ Action bdReg = nxLoadRegAction(NxmNxReg4.class,
+ BigInteger.valueOf(bdId));
+ Action fdReg = nxLoadRegAction(NxmNxReg5.class,
+ BigInteger.valueOf(fdId));
+ Action vrfReg = nxLoadRegAction(NxmNxReg6.class,
+ BigInteger.valueOf(l3Id));
+ FlowBuilder flowb = base()
+ .setId(flowid)
+ .setPriority(Integer.valueOf(150))
+ .setMatch(mb.build())
+ .setInstructions(instructions(applyActionIns(segReg,
+ scgReg,
+ bdReg,
+ fdReg,
+ vrfReg),
+ gotoTableIns((short)(TABLE_ID + 1))));
+ writeFlow(t, tiid, flowb.build());
+ }
+ }
+
for (Endpoint e : ctx.epManager.getEPsForNode(nodeId, sepg)) {
OfOverlayContext ofc = e.getAugmentation(OfOverlayContext.class);
if (ofc != null && ofc.getNodeConnectorId() != null &&
(ofc.getLocationType() == null ||
LocationType.Internal.equals(ofc.getLocationType())) &&
e.getTenant() != null && e.getEndpointGroup() != null) {
- syncEP(t, tiid, flowMap, policyInfo, nodeId, e, ofc);
+ syncEP(t, tiid, flowMap, policyInfo, nodeId, e, ofc,
+ egId, bdId, fdId, l3Id);
}
}
}
InstanceIdentifier<Table> tiid,
Map<String, FlowCtx> flowMap,
PolicyInfo policyInfo,
- NodeId nodeId, Endpoint e, OfOverlayContext ofc)
+ NodeId nodeId, Endpoint e, OfOverlayContext ofc,
+ int egId, int bdId, int fdId, int l3Id)
throws Exception {
// Set sEPG, flood domain, bridge domain, and layer 3 context
// for internal endpoints by directly matching each endpoint
- IndexedTenant tenant = ctx.policyResolver.getTenant(e.getTenant());
- if (tenant == null) return;
-
- EndpointGroup eg = tenant.getEndpointGroup(e.getEndpointGroup());
- L3Context l3c = tenant.resolveL3Context(eg.getNetworkDomain());
- L2BridgeDomain bd = tenant.resolveL2BridgeDomain(eg.getNetworkDomain());
- L2FloodDomain fd = tenant.resolveL2FloodDomain(eg.getNetworkDomain());
- int egId = 0, bdId = 0, fdId = 0, l3Id = 0, cgId = 0;
-
- egId = ctx.policyManager.getContextOrdinal(e.getTenant(),
- e.getEndpointGroup());
- if (bd != null)
- bdId = ctx.policyManager.getContextOrdinal(e.getTenant(),
- bd.getId());
- if (fd != null)
- fdId = ctx.policyManager.getContextOrdinal(e.getTenant(),
- fd.getId());
- if (l3c != null)
- l3Id = ctx.policyManager.getContextOrdinal(e.getTenant(),
- l3c.getId());
List<ConditionName> conds = ctx.epManager.getCondsForEndpoint(e);
ConditionGroup cg =
policyInfo.getEgCondGroup(new EgKey(e.getTenant(),
e.getEndpointGroup()),
conds);
- cgId = ctx.policyManager.getConfGroupOrdinal(cg);
-
+ int cgId = ctx.policyManager.getCondGroupOrdinal(cg);
+
FlowId flowid = new FlowId(new StringBuilder()
- .append(ofc.getNodeConnectorId())
+ .append(ofc.getNodeConnectorId().getValue())
.append("|")
.append(e.getMacAddress().getValue())
.append("|")
.append(cgId)
.toString());
if (visit(flowMap, flowid.getValue())) {
- LOG.info("{} seg:{} bd:{} fd:{} vrf:{} scg:{}",
- e.getMacAddress(), egId, bdId, fdId, l3Id, cgId);
+ Action segReg = nxLoadRegAction(NxmNxReg0.class,
+ BigInteger.valueOf(egId));
+ Action scgReg = nxLoadRegAction(NxmNxReg1.class,
+ BigInteger.valueOf(cgId));
+ Action bdReg = nxLoadRegAction(NxmNxReg4.class,
+ BigInteger.valueOf(bdId));
+ Action fdReg = nxLoadRegAction(NxmNxReg5.class,
+ BigInteger.valueOf(fdId));
+ Action vrfReg = nxLoadRegAction(NxmNxReg6.class,
+ BigInteger.valueOf(l3Id));
FlowBuilder flowb = base()
.setPriority(Integer.valueOf(100))
.setId(flowid)
.setMatch(new MatchBuilder()
- .setEthernetMatch(FlowUtils.ethernetMatch(e.getMacAddress(),
- null, null))
+ .setEthernetMatch(ethernetMatch(e.getMacAddress(),
+ null, null))
.setInPort(ofc.getNodeConnectorId())
.build())
- // XXX TODO set sepg, bd, fd, vrf, scg into registers
- .setInstructions(FlowUtils.gotoTableInstructions((short)(TABLE_ID + 1)));
+ .setInstructions(instructions(applyActionIns(segReg,
+ scgReg,
+ bdReg,
+ fdReg,
+ vrfReg),
+ gotoTableIns((short)(TABLE_ID + 1))));
writeFlow(t, tiid, flowb.build());
}
}
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
package org.opendaylight.groupbasedpolicy.resolver;
import java.util.List;
description
"A classifier is used to match traffic traveling between
the endpoint groups that form the contract.
- Classifier defintions can define parameters that
+ Classifier definitions can define parameters that
will need to be filled in when a particular rule
references it.";
description "The IP prefix that defines the subnet";
type inet:ip-prefix;
}
+ leaf virtual-router-ip {
+ description
+ "IP address to use for a virtual gateway router
+ for the subnet, if desired.";
+ type inet:ip-address;
+ }
}
// ***************
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+import java.math.BigInteger;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.mockito.Matchers;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
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.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
-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.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.mockito.Mockito.*;
-public class DestinationMapperTest extends OfTableTest {
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
+
+public class DestinationMapperTest extends FlowTableTest {
protected static final Logger LOG =
LoggerFactory.getLogger(DestinationMapperTest.class);
- NodeConnectorId tunnelId =
- new NodeConnectorId(nodeId.getValue() + ":42");
NodeConnectorId remoteTunnelId =
- new NodeConnectorId(remoteNodeId.getValue() + ":42");
+ new NodeConnectorId(remoteNodeId.getValue() + ":101");
@Before
public void setup() throws Exception {
for (Flow f : ac.getAllValues()) {
flowMap.put(f.getId().getValue(), new FlowCtx(f));
if (f.getMatch() == null) {
- assertEquals(FlowUtils.dropInstructions(),
+ assertEquals(dropInstructions(),
f.getInstructions());
count += 1;
+ } else if (Objects.equals(ethernetMatch(null, null, ARP),
+ f.getMatch().getEthernetMatch())) {
+ // router ARP reply
+ Instruction ins = f.getInstructions().getInstruction().get(0);
+ ins = f.getInstructions().getInstruction().get(0);
+ assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
+ List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
+ assertEquals(nxMoveEthSrcToEthDstAction(),
+ actions.get(0).getAction());
+ assertEquals(Integer.valueOf(0), actions.get(0).getOrder());
+ assertEquals(setDlSrcAction(DestinationMapper.ROUTER_MAC),
+ actions.get(1).getAction());
+ assertEquals(Integer.valueOf(1), actions.get(1).getOrder());
+ assertEquals(nxLoadArpOpAction(BigInteger.valueOf(2L)),
+ actions.get(2).getAction());
+ assertEquals(Integer.valueOf(2), actions.get(2).getOrder());
+ assertEquals(nxMoveArpShaToArpThaAction(),
+ actions.get(3).getAction());
+ assertEquals(Integer.valueOf(3), actions.get(3).getOrder());
+ assertEquals(nxLoadArpShaAction(new BigInteger(1, HexEncode
+ .bytesFromHexString(DestinationMapper.ROUTER_MAC
+ .getValue()))),
+ actions.get(4).getAction());
+ assertEquals(Integer.valueOf(4), actions.get(4).getOrder());
+ assertEquals(nxMoveArpSpaToArpTpaAction(),
+ actions.get(5).getAction());
+ assertEquals(Integer.valueOf(5), actions.get(5).getOrder());
+ assertTrue(nxLoadArpSpaAction("10.0.0.1").equals(actions.get(6).getAction()) ||
+ nxLoadArpSpaAction("10.0.0.2").equals(actions.get(6).getAction()));
+ assertEquals(Integer.valueOf(6), actions.get(6).getOrder());
+ count += 1;
} else if (Objects.equals(localEp.getMacAddress(),
f.getMatch().getEthernetMatch()
.getEthernetDestination().getAddress())) {
int icount = 0;
for (Instruction ins : f.getInstructions().getInstruction()) {
- if (ins.getInstruction() instanceof WriteActionsCase) {
- assertEquals(FlowUtils.outputActionIns(nodeConnectorId),
- ins.getInstruction());
+ if (ins.getInstruction() instanceof ApplyActionsCase) {
+ long p = OfTable.getOfPortNum(nodeConnectorId);
+ List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
+ assertEquals(nxLoadRegAction(NxmNxReg7.class,
+ BigInteger.valueOf(p)),
+ actions.get(2).getAction());
icount += 1;
} else if (ins.getInstruction() instanceof GoToTableCase) {
- assertEquals(FlowUtils.gotoTableIns((short)(table.getTableId()+1)),
+ assertEquals(gotoTableIns((short)(table.getTableId()+1)),
ins.getInstruction());
icount += 1;
}
.getEthernetDestination().getAddress())) {
int icount = 0;
for (Instruction ins : f.getInstructions().getInstruction()) {
- if (ins.getInstruction() instanceof WriteActionsCase) {
- assertEquals(FlowUtils.outputActionIns(tunnelId),
- ins.getInstruction());
+ if (ins.getInstruction() instanceof ApplyActionsCase) {
+ long p = OfTable.getOfPortNum(tunnelId);
+ List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
+ assertEquals(nxLoadRegAction(NxmNxReg7.class,
+ BigInteger.valueOf(p)),
+ actions.get(4).getAction());
icount += 1;
} else if (ins.getInstruction() instanceof GoToTableCase) {
- assertEquals(FlowUtils.gotoTableIns((short)(table.getTableId()+1)),
+ assertEquals(gotoTableIns((short)(table.getTableId()+1)),
ins.getInstruction());
icount += 1;
}
// should be local port with rewrite dlsrc and dldst plus
// ttl decr
Instruction ins = f.getInstructions().getInstruction().get(0);
- assertTrue(ins.getInstruction() instanceof WriteActionsCase);
- List<Action> actions =
- ((WriteActionsCase)ins.getInstruction()).getWriteActions().getAction();
- assertEquals(FlowUtils.setDlSrc(DestinationMapper.ROUTER_MAC),
- actions.get(0).getAction());
- assertEquals(Integer.valueOf(0), actions.get(0).getOrder());
- assertEquals(FlowUtils.setDlDst(localEp.getMacAddress()),
- actions.get(1).getAction());
- assertEquals(Integer.valueOf(1), actions.get(1).getOrder());
- assertEquals(FlowUtils.decNwTtl(),
+ assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
+ List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
+ long p = OfTable.getOfPortNum(nodeConnectorId);
+ assertEquals(nxLoadRegAction(NxmNxReg7.class,
+ BigInteger.valueOf(p)),
actions.get(2).getAction());
assertEquals(Integer.valueOf(2), actions.get(2).getOrder());
- assertEquals(FlowUtils.outputAction(nodeConnectorId),
+ assertEquals(setDlSrcAction(DestinationMapper.ROUTER_MAC),
actions.get(3).getAction());
assertEquals(Integer.valueOf(3), actions.get(3).getOrder());
+ assertEquals(setDlDstAction(localEp.getMacAddress()),
+ actions.get(4).getAction());
+ assertEquals(Integer.valueOf(4), actions.get(4).getOrder());
+ assertEquals(decNwTtlAction(),
+ actions.get(5).getAction());
+ assertEquals(Integer.valueOf(5), actions.get(5).getOrder());
count += 1;
} else if (f.getMatch().getLayer3Match() instanceof Ipv6Match) {
// should be remote port with rewrite dlsrc plus
// ttl decr
Instruction ins = f.getInstructions().getInstruction().get(0);
- assertTrue(ins.getInstruction() instanceof WriteActionsCase);
- List<Action> actions =
- ((WriteActionsCase)ins.getInstruction()).getWriteActions().getAction();
- assertEquals(FlowUtils.setDlSrc(DestinationMapper.ROUTER_MAC),
- actions.get(0).getAction());
- assertEquals(Integer.valueOf(0), actions.get(0).getOrder());
- assertEquals(FlowUtils.decNwTtl(),
- actions.get(1).getAction());
- assertEquals(Integer.valueOf(1), actions.get(1).getOrder());
- assertEquals(FlowUtils.outputAction(tunnelId),
- actions.get(2).getAction());
- assertEquals(Integer.valueOf(2), actions.get(2).getOrder());
+ assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
+ List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
+ long p = OfTable.getOfPortNum(tunnelId);
+ assertEquals(nxLoadRegAction(NxmNxReg7.class,
+ BigInteger.valueOf(p)),
+ actions.get(4).getAction());
+ assertEquals(Integer.valueOf(4), actions.get(4).getOrder());
+ assertEquals(setDlSrcAction(DestinationMapper.ROUTER_MAC),
+ actions.get(5).getAction());
+ assertEquals(Integer.valueOf(5), actions.get(5).getOrder());
+ assertEquals(decNwTtlAction(),
+ actions.get(6).getAction());
+ assertEquals(Integer.valueOf(6), actions.get(6).getOrder());
count += 1;
}
+ } else if (Objects.equals(DestinationMapper.MULTICAST_MAC,
+ f.getMatch().getEthernetMatch()
+ .getEthernetDestination()
+ .getAddress())) {
+ // broadcast/multicast flow should output to group table
+ Instruction ins = f.getInstructions().getInstruction().get(0);
+ ins = f.getInstructions().getInstruction().get(0);
+ assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
+ List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
+ assertEquals(nxMoveRegTunIdAction(NxmNxReg0.class, false),
+ actions.get(0).getAction());
+ assertEquals(Integer.valueOf(0), actions.get(0).getOrder());
+ Long v = Long.valueOf(policyManager.getContextOrdinal(tid, fd));
+ assertEquals(groupAction(v), actions.get(1).getAction());
+ assertEquals(Integer.valueOf(1), actions.get(1).getOrder());
+ count += 1;
}
}
- assertEquals(5, count);
+ assertEquals(7, count);
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
@Override
protected EndpointBuilder remoteEP(NodeId remoteNodeId) {
return super.remoteEP(remoteNodeId)
- .setMacAddress(new MacAddress("00:00:00:00:00:02"))
.setL3Address(ImmutableList.of(new L3AddressBuilder()
.setL3Context(l3c)
.setIpAddress(new IpAddress(new Ipv6Address("::ffff:0:0::10.0.0.2")))
switchManager.addSwitch(remoteNodeId, remoteTunnelId,
Collections.<NodeConnectorId>emptySet(),
new OfOverlayNodeConfigBuilder()
- .setTunnelIp(new IpAddress(new Ipv6Address("::1:2:3:4")))
+ .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.5")))
.build());
}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static org.mockito.Mockito.*;
+
+public class FlowTableTest extends OfTableTest {
+ FlowTable table;
+ InstanceIdentifier<Table> tiid;
+
+ protected void setup() throws Exception {
+ tiid = FlowUtils.createTablePath(nodeId,
+ table.getTableId());
+ }
+
+ protected ReadWriteTransaction dosync(Map<String, FlowCtx> flowMap)
+ throws Exception {
+ ReadWriteTransaction t = mock(ReadWriteTransaction.class);
+ if (flowMap == null)
+ flowMap = Collections.emptyMap();
+ table.sync(t, tiid, flowMap, nodeId, policyResolver.getCurrentPolicy(),
+ null);
+ return t;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+
+import java.util.Collections;
+import java.util.HashMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.GroupTable.BucketCtx;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.GroupTable.GroupCtx;
+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.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+
+import static org.junit.Assert.*;
+
+public class GroupTableTest extends OfTableTest {
+ protected static final Logger LOG =
+ LoggerFactory.getLogger(GroupTableTest.class);
+
+ GroupTable table;
+
+ NodeConnectorId tunnelId =
+ new NodeConnectorId(nodeId.getValue() + ":42");
+ NodeConnectorId remoteTunnelId =
+ new NodeConnectorId(remoteNodeId.getValue() + ":101");
+
+ @Before
+ public void setup() throws Exception {
+ initCtx();
+ table = new GroupTable(ctx);
+ }
+
+ @Test
+ public void testGroup() throws Exception {
+ Endpoint localEp = localEP().build();
+ endpointManager.addEndpoint(localEp);
+ Endpoint remoteEp = remoteEP(remoteNodeId).build();
+ endpointManager.addEndpoint(remoteEp);
+
+ switchManager.addSwitch(nodeId, tunnelId,
+ Collections.<NodeConnectorId>emptySet(),
+ new OfOverlayNodeConfigBuilder()
+ .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.4")))
+ .build());
+ switchManager.addSwitch(remoteNodeId, remoteTunnelId,
+ Collections.<NodeConnectorId>emptySet(),
+ new OfOverlayNodeConfigBuilder()
+ .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.5")))
+ .build());
+
+ policyResolver.addTenant(baseTenant().build());
+
+ HashMap<GroupId, GroupCtx> groupMap = new HashMap<>();
+ table.sync(nodeId, ctx.policyResolver.getCurrentPolicy(),
+ null, groupMap);
+
+ assertEquals(1, groupMap.size());
+ int fdId = ctx.policyManager.getContextOrdinal(tid, fd);
+ GroupCtx ctx = groupMap.get(new GroupId(Long.valueOf(fdId)));
+ assertNotNull(ctx);
+ long tunBucketId =
+ (long)policyManager.getContextOrdinal(remoteNodeId.getValue());
+ tunBucketId |= 1L << 31;
+
+ int count = 0;
+ for (BucketCtx bctx : ctx.bucketMap.values()) {
+ if (Objects.equal(Long.valueOf(4),
+ bctx.newb.getBucketId().getValue())) {
+ count += 1;
+ } else if (Objects.equal(Long.valueOf(tunBucketId),
+ bctx.newb.getBucketId().getValue())) {
+
+ count += 1;
+ }
+ }
+ assertEquals(2, count);
+ }
+}
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
-import java.util.Collections;
-import java.util.Map;
-
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockEndpointManager;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockPolicyManager;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockSwitchManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OfTable.OfTableCtx;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.L4Classifier;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
import org.opendaylight.groupbasedpolicy.resolver.MockPolicyResolver;
+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.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.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.flow.inventory.rev130819.tables.Table;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstanceBuilder;
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.yangtools.yang.binding.InstanceIdentifier;
import com.google.common.collect.ImmutableList;
-import static org.mockito.Mockito.*;
-
public class OfTableTest {
OfTableCtx ctx;
- FlowTable table;
-
+
MockEndpointManager endpointManager;
MockPolicyResolver policyResolver;
MockPolicyManager policyManager;
NodeId nodeId = new NodeId("openflow:1");
NodeId remoteNodeId = new NodeId("openflow:2");
NodeConnectorId nodeConnectorId =
- new NodeConnectorId(nodeId.getValue() + ":1");
- InstanceIdentifier<Table> tiid;
-
+ new NodeConnectorId(nodeId.getValue() + ":4");
+
+ NodeConnectorId tunnelId =
+ new NodeConnectorId(nodeId.getValue() + ":42");
+
L3ContextId l3c = new L3ContextId("2cf51ee4-e996-467e-a277-2d380334a91d");
L2BridgeDomainId bd = new L2BridgeDomainId("c95182ba-7807-43f8-98f7-6c7c720b7639");
L2FloodDomainId fd = new L2FloodDomainId("98e1439e-52d2-46f8-bd69-5136e6088771");
endpointManager,
null);
}
-
- protected void setup() throws Exception {
- tiid = FlowUtils.createTablePath(nodeId,
- table.getTableId());
- }
protected TenantBuilder baseTenant() {
return baseTenant(null);
.setId(sub2)
.setParent(fd)
.setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.1.1/24")))
+ .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.1.1")))
.build(),
new SubnetBuilder()
.setId(sub)
.setParent(fd)
.setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.0.1/24")))
+ .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.0.1")))
.build()))
.setSubjectFeatureInstances(new SubjectFeatureInstancesBuilder()
.setClassifierInstance(ImmutableList.of(new ClassifierInstanceBuilder()
protected EndpointBuilder remoteEP(NodeId id) {
OfOverlayContext ofc = new OfOverlayContextBuilder()
.setNodeId(id)
- .setNodeConnectorId(new NodeConnectorId(id.getValue() + ":1"))
+ .setNodeConnectorId(new NodeConnectorId(id.getValue() + ":5"))
.build();
return baseEP()
+ .setMacAddress(new MacAddress("00:00:00:00:00:02"))
.addAugmentation(OfOverlayContext.class, ofc);
}
- protected ReadWriteTransaction dosync(Map<String, FlowCtx> flowMap)
- throws Exception {
- ReadWriteTransaction t = mock(ReadWriteTransaction.class);
- if (flowMap == null)
- flowMap = Collections.emptyMap();
- table.sync(t, tiid, flowMap, nodeId, policyResolver.getCurrentPolicy(),
- null);
- return t;
- }
-
}
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Objects;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
+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.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.mockito.Mockito.*;
-public class PolicyEnforcerTest extends OfTableTest {
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
+
+public class PolicyEnforcerTest extends FlowTableTest {
protected static final Logger LOG =
LoggerFactory.getLogger(PolicyEnforcerTest.class);
initCtx();
table = new PolicyEnforcer(ctx);
super.setup();
+
+ switchManager.addSwitch(nodeId, tunnelId,
+ Collections.<NodeConnectorId>emptySet(),
+ new OfOverlayNodeConfigBuilder()
+ .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.4")))
+ .build());
}
@Test
public void testNoEps() throws Exception {
ReadWriteTransaction t = dosync(null);
- verify(t, times(1)).put(any(LogicalDatastoreType.class),
+ verify(t, times(2)).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
any(Flow.class), anyBoolean());
}
HashMap<String, FlowCtx> flowMap = new HashMap<>();
for (Flow f : ac.getAllValues()) {
flowMap.put(f.getId().getValue(), new FlowCtx(f));
- // XXX - TODO check actual match/action
if (f.getId().getValue().indexOf("intraallow") == 0)
count += 1;
}
flowMap.put(f.getId().getValue(), new FlowCtx(f));
if (f.getId().getValue().indexOf("intraallow") == 0) {
count += 1;
+ } else if (f.getMatch() != null &&
+ Objects.equals(tunnelId, f.getMatch().getInPort())) {
+ assertEquals(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))),
+ f.getInstructions());
+ count += 1;
} else if (f.getMatch() != null &&
f.getMatch().getEthernetMatch() != null &&
Objects.equals(FlowUtils.IPv4,
Objects.equals(Integer.valueOf(80),
((TcpMatch)f.getMatch().getLayer4Match())
.getTcpDestinationPort().getValue())) {
- // XXX - TODO - verify sepg/depg
count += 1;
} else if (f.getMatch() != null &&
f.getMatch().getEthernetMatch() != null &&
Objects.equals(Integer.valueOf(80),
((TcpMatch)f.getMatch().getLayer4Match())
.getTcpDestinationPort().getValue())) {
- // XXX - TODO - verify sepg/depg
count += 1;
- }
+ }
}
if (direction == null || direction.equals(Direction.Bidirectional))
- assertEquals(6, count);
+ assertEquals(7, count);
else
- assertEquals(4, count);
+ assertEquals(5, count);
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
import static org.mockito.Mockito.*;
-public class PortSecurityTest extends OfTableTest {
+public class PortSecurityTest extends FlowTableTest {
protected static final Logger LOG =
LoggerFactory.getLogger(PortSecurityTest.class);
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+import java.math.BigInteger;
import java.util.HashMap;
+import java.util.List;
import java.util.Objects;
import org.junit.Before;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
+import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
+import org.opendaylight.groupbasedpolicy.resolver.EgKey;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.mockito.Mockito.*;
-public class SourceMapperTest extends OfTableTest {
+public class SourceMapperTest extends FlowTableTest {
protected static final Logger LOG =
LoggerFactory.getLogger(SourceMapperTest.class);
@Before
} else if (Objects.equals(ep.getMacAddress(),
f.getMatch().getEthernetMatch()
.getEthernetSource().getAddress())) {
- // XXX TODO verify register setting in the instructions
- LOG.info("{}", f);
+ PolicyInfo pi = policyResolver.getCurrentPolicy();
+ List<ConditionName> cset = endpointManager.getCondsForEndpoint(ep);
+ ConditionGroup cg = pi.getEgCondGroup(new EgKey(tid, eg), cset);
+
+ Instruction ins = f.getInstructions().getInstruction().get(0);
+ assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
+ List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
+ int v = policyManager.getContextOrdinal(tid, eg);
+ assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg0.class,
+ BigInteger.valueOf(v)),
+ actions.get(0).getAction());
+ v = policyManager.getCondGroupOrdinal(cg);
+ assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg1.class,
+ BigInteger.valueOf(v)),
+ actions.get(1).getAction());
+ v = policyManager.getContextOrdinal(tid, bd);
+ assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg4.class,
+ BigInteger.valueOf(v)),
+ actions.get(2).getAction());
+ v = policyManager.getContextOrdinal(tid, fd);
+ assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg5.class,
+ BigInteger.valueOf(v)),
+ actions.get(3).getAction());
+ v = policyManager.getContextOrdinal(tid, l3c);
+ assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg6.class,
+ BigInteger.valueOf(v)),
+ actions.get(4).getAction());
count += 1;
}
}
<module>groupbasedpolicy</module>
<module>distribution</module>
</modules>
+
<build>
<plugins>
<plugin>
--- /dev/null
+
+
+TENANT="f5c7d344-d1c7-4208-8531-2c2693657e12"
+L3CTX="f2311f52-890f-4095-8b85-485ec8b92b3c"
+L2BD="70aeb9ea-4ca1-4fb9-9780-22b04b84a0d6"
+
+L2FD1="252fbac6-bb6e-4d16-808d-6f56d20e5cca"
+EG1="1eaf9a67-a171-42a8-9282-71cf702f61dd"
+L2FD2="cb5249bb-e896-45be-899d-4cdd9354b58e"
+EG2="e593f05d-96be-47ad-acd5-ba81465680d5"
+
+CONTRACT="22282cca-9a13-4d0c-a67e-a933ebb0b0ae"
+
+switches = [{'name': 's1',
+ 'tunnelIp': '10.160.9.20',
+ 'dpid': '1'},
+ {'name': 's2',
+ 'tunnelIp': '10.160.9.21',
+ 'dpid': '2'}]
+
+hosts = [{'name': 'h35_2',
+ 'mac': '00:00:00:00:35:02',
+ 'ip': '10.0.35.2/24',
+ 'switch': 's1',
+ 'tenant': TENANT,
+ 'endpointGroup': EG1},
+ {'name': 'h35_3',
+ 'ip': '10.0.35.3/24',
+ 'mac': '00:00:00:00:35:03',
+ 'switch': 's1',
+ 'tenant': TENANT,
+ 'endpointGroup': EG1},
+ {'name': 'h35_4',
+ 'ip': '10.0.35.4/24',
+ 'mac': '00:00:00:00:35:04',
+ 'switch': 's2',
+ 'tenant': TENANT,
+ 'endpointGroup': EG1},
+ {'name': 'h35_5',
+ 'ip': '10.0.35.5/24',
+ 'mac': '00:00:00:00:35:05',
+ 'switch': 's2',
+ 'tenant': TENANT,
+ 'endpointGroup': EG1},
+ {'name': 'h36_2',
+ 'ip': '10.0.36.2/24',
+ 'mac': '00:00:00:00:36:02',
+ 'switch': 's1',
+ 'tenant': TENANT,
+ 'endpointGroup': EG2},
+ {'name': 'h36_3',
+ 'ip': '10.0.36.3/24',
+ 'mac': '00:00:00:00:36:03',
+ 'switch': 's1',
+ 'tenant': TENANT,
+ 'endpointGroup': EG2},
+ {'name': 'h36_4',
+ 'ip': '10.0.36.4/24',
+ 'mac': '00:00:00:00:36:04',
+ 'switch': 's2',
+ 'tenant': TENANT,
+ 'endpointGroup': EG2},
+ {'name': 'h36_5',
+ 'ip': '10.0.36.5/24',
+ 'mac': '00:00:00:00:36:05',
+ 'switch': 's2',
+ 'tenant': TENANT,
+ 'endpointGroup': EG2}]
+
+contracts = [{'consumer': EG1,
+ 'provider': EG2,
+ 'id': CONTRACT}]
--- /dev/null
+
+from mininet.topo import Topo
+from mininet.node import RemoteController
+from mininet.net import Mininet
+from mininet.util import dumpNodeConnections
+from mininet.log import setLogLevel
+from mininet.node import Node
+
+import re
+import time
+from subprocess import call
+from subprocess import check_output
+
+def addSwitch(net, name, dpid=None):
+ switch = net.addSwitch(name, dpid=dpid)
+ return switch
+
+def addHost(net, switch, name, ip, mac):
+ host = net.addHost(name, ip=ip, mac=mac)
+ net.addLink(host, switch)
+
+def setOFVersion(sw, version='OpenFlow13'):
+ call(['ovs-vsctl', 'set', 'bridge', sw, 'protocols={}'.format(version)])
+
+def addTunnel(sw, sourceIp=None):
+ ifaceName = '{}_vxlan0'.format(sw)
+ cmd = ['ovs-vsctl', 'add-port', sw, ifaceName,
+ '--', 'set', 'Interface', ifaceName,
+ 'type=vxlan',
+ 'options:remote_ip=flow',
+ 'options:key=flow']
+ if sourceIp is not None:
+ cmd.append('options:source_ip={}'.format(sourceIp))
+ call(cmd)
+
+#ovs-ofctl dump-ports-desc s1 -OOpenFlow13
+
+def startMininet(switches, hosts, contIP='127.0.0.1'):
+ setLogLevel('info')
+
+ net = Mininet(controller=None,
+ autoSetMacs=True,
+ listenPort=6634)
+ net.addController('c0', controller=RemoteController,
+ ip=contIP, port=6653)
+
+ swobjs = {}
+ swports = {}
+
+ for sw in switches:
+ swobj = addSwitch(net, sw['name'])
+ swobjs[sw['name']] = swobj
+ swports[sw['name']] = 0;
+ for host in hosts:
+ if host['switch'] not in swobjs:
+ continue
+ sw = swobjs[host['switch']]
+ swports[host['switch']] += 1;
+ port = swports[host['switch']]
+ addHost(net, sw, host['name'], host['ip'], host['mac'])
+ host['port'] = port
+
+ try:
+ net.start()
+ for sw in switches:
+ addTunnel(sw['name'], sw['tunnelIp'])
+
+ for host in net.hosts:
+ gw = re.sub(r'.\d+$', ".1", host.IP())
+ host.cmd('route add default gw {}'.format(gw))
+
+ # ODL is very fragile so let's give it some time
+ time.sleep(1)
+
+ for sw in switches:
+ setOFVersion(sw['name'])
+
+ return net
+ except Exception, e:
+ net.stop()
+ raise e
--- /dev/null
+
+import requests,json
+
+REGISTER_EP_URL="http://%s:8080/restconf/operations/endpoint:register-endpoint"
+REGISTER_TENANTS_URL="http://%s:8080/restconf/config/policy:tenants"
+REGISTER_NODES_URL="http://%s:8080/restconf/config/opendaylight-inventory:nodes"
+
+endpointGroups = {}
+
+def get_epg(tenantId, epgId):
+ k = "{}|{}".format(tenantId,epgId)
+ if k in endpointGroups:
+ return endpointGroups[k]
+ tenant = get_tenant(tenantId);
+ data = {
+ "id": epgId,
+ "consumer-named-selector": [],
+ "provider-named-selector": []
+ }
+ tenant["endpoint-group"].append(data)
+ endpointGroups[k] = data
+ return data
+
+tenants = {}
+
+def get_tenant(tenantId):
+ if tenantId in tenants:
+ return tenants[tenantId]
+ data = {
+ "id": tenantId,
+ "l3-context": [],
+ "l2-bridge-domain": [],
+ "l2-flood-domain": [],
+ "subnet": [],
+ "endpoint-group": [],
+ "contract": [],
+ "subject-feature-instances": {
+ "classifier-instance": [
+ {"name": "http-dest",
+ "classifier-definition-id": "4250ab32-e8b8-445a-aebb-e1bd2cdd291f",
+ "parameter-value": [
+ {"name": "type",
+ "string-value": "TCP"},
+ {"name": "destport",
+ "int-value": "80"}
+ ]},
+ {"name": "http-src",
+ "classifier-definition-id": "4250ab32-e8b8-445a-aebb-e1bd2cdd291f",
+ "parameter-value": [
+ {"name": "type",
+ "string-value": "TCP"},
+ {"name": "sourceport",
+ "int-value": "80"}
+ ]},
+ {"name": "icmp",
+ "classifier-definition-id": "79c6fdb2-1e1a-4832-af57-c65baf5c2335",
+ "parameter-value": [
+ {"name": "proto",
+ "int-value": "1"}
+ ]},
+ ]
+ }
+ }
+ tenants[tenantId] = data
+ return data
+
+subnets = {}
+
+def get_fd(tenantId, fdId, parent):
+ tenant = get_tenant(tenantId)
+ data = {"id": fdId,
+ "parent": parent}
+ tenant["l2-flood-domain"].append(data)
+ return data
+
+def get_bd(tenantId, bdId, parent):
+ tenant = get_tenant(tenantId)
+ data = {"id": bdId,
+ "parent": parent}
+ tenant["l2-bridge-domain"].append(data)
+ return data
+
+def get_l3c(tenantId, l3cId):
+ tenant = get_tenant(tenantId)
+ data = {"id": l3cId}
+ tenant["l3-context"].append(data)
+ return data
+
+def get_subnet(tenantId, subnetId, parent, prefix, router):
+ k = "{}|{}".format(tenantId, subnetId)
+ if k in subnets:
+ return subnets[k]
+ tenant = get_tenant(tenantId)
+ data = {"id": subnetId,
+ "parent": parent,
+ "ip-prefix": prefix,
+ "virtual-router-ip": router}
+ tenant["subnet"].append(data)
+ return data
+
+endpoints = []
+
+def get_ep(tenantId, groupId, l3ctx, ip, l2ctx, mac, sw, port):
+ group = get_epg(tenantId, groupId)
+ data = {"tenant": tenantId,
+ "endpoint-group": groupId,
+ "l2-context": l2ctx,
+ "mac-address": mac,
+ "l3-address": [{"l3-context": l3ctx,
+ "ip-address": ip}],
+ "ofoverlay:node-id": "openflow:{}".format(sw),
+ "ofoverlay:node-connector-id": "openflow:{}:{}".format(sw, port)
+ }
+ endpoints.append(data)
+ return data
+
+nodes = []
+
+def get_node_config(sw, tun_ip):
+ data = {
+ "id": "openflow:{}".format(sw),
+ "ofoverlay:tunnel-ip": tun_ip
+ }
+ nodes.append(data)
+ return data
+
+def get_contract(tenantId, pgroupId, cgroupId, contractId):
+ tenant = get_tenant(tenantId)
+ pgroup = get_epg(tenantId, pgroupId)
+ cgroup = get_epg(tenantId, cgroupId)
+ data = {
+ "id": contractId,
+ "subject": [{"name": "allow-http-subject",
+ "rule": [
+ {"name": "allow-http-rule",
+ "classifier-ref": [
+ {"name": "http-dest",
+ "direction": "in"},
+ {"name": "http-src",
+ "direction": "out"}
+ ]}
+ ]},
+ {"name": "allow-icmp-subject",
+ "rule": [
+ {"name": "allow-icmp-rule",
+ "classifier-ref": [
+ {"name": "icmp"}
+ ]}
+ ]}],
+ "clause": [{"name": "allow-http-clause",
+ "subject-refs": ["allow-http-subject",
+ "allow-icmp-subject"]}]
+ }
+ tenant["contract"].append(data)
+ cgroup["consumer-named-selector"].append({
+ "name": "{}-{}-{}".format(pgroupId, cgroupId, contractId),
+ "contract": [contractId]
+ })
+ pgroup["provider-named-selector"].append({
+ "name": "{}-{}-{}".format(pgroupId, cgroupId, contractId),
+ "contract": [contractId]
+ })
+
+ return data
+
+def post(url, data):
+ headers = {'Content-type': 'application/yang.data+json',
+ 'Accept': 'application/yang.data+json'}
+ print "POST %s" % url
+ print json.dumps(data, indent=4, sort_keys=True)
+ r = requests.post(url, data=json.dumps(data), headers=headers)
+ print r.text
+ r.raise_for_status()
+
+def put(url, data):
+ headers = {'Content-type': 'application/yang.data+json',
+ 'Accept': 'application/yang.data+json'}
+ print "PUT %s" % url
+ print json.dumps(data, indent=4, sort_keys=True)
+ r = requests.put(url, data=json.dumps(data), headers=headers)
+ print r.text
+ r.raise_for_status()
+
+def register_tenants(contHost):
+ data = {"policy:tenants": {"tenant": tenants.values()}}
+ put(REGISTER_TENANTS_URL % contHost, data)
+
+def register_eps(contHost):
+ for ep in endpoints:
+ data = {"input": ep}
+ post(REGISTER_EP_URL % contHost, data)
+
+def register_nodes(contHost):
+ data = {"opendaylight-inventory:nodes": {"node": nodes}}
+ put(REGISTER_NODES_URL % contHost, data)
--- /dev/null
+#!/usr/bin/python
+
+import mininet_gbp
+import odl_gbp
+import mininet.cli
+import ipaddr
+import uuid
+import re
+import argparse, sys
+from config import *
+
+def getSubnet(ip):
+ nw = ipaddr.IPv4Network(ip)
+ return "{}/{}".format(nw.network + 1, nw.prefixlen)
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--local',
+ help='Set up distributed mininet on local host with the specified switch')
+ parser.add_argument('--policy', action='store_true',
+ help='Configure the policy on the controller')
+ parser.add_argument('--controller', default='127.0.0.1',
+ help='Use the specified controller IP address')
+ args = parser.parse_args()
+
+ if (not args.local and not args.policy):
+ parser.print_help()
+ sys.exit(3)
+
+ conf_switches = []
+ if args.local:
+ for switch in switches:
+ if switch['name'] == args.local:
+ conf_switches = [switch]
+ break
+
+ net = None
+ if len(conf_switches) > 0:
+ net = mininet_gbp.startMininet(conf_switches, hosts, args.controller)
+ try :
+ if args.policy:
+ for switch in switches:
+ odl_gbp.get_node_config(switch['dpid'], switch['tunnelIp'])
+
+ odl_gbp.register_nodes(args.controller)
+
+ tenant = odl_gbp.get_tenant(TENANT)
+ odl_gbp.get_l3c(TENANT, L3CTX)
+ odl_gbp.get_bd(TENANT, L2BD, L3CTX)
+
+ subnets = {}
+ fds = {}
+ for host in hosts:
+ if args.local and host['switch'] != args.local:
+ continue
+ nw = ipaddr.IPv4Network(host['ip'])
+ snet = "{}/{}".format(nw.network + 1, nw.prefixlen)
+ router = "{}".format(nw.network + 1)
+
+ if snet not in subnets:
+ snid = str(uuid.uuid4())
+ fdid = str(uuid.uuid4())
+ fds[fdid] = odl_gbp.get_fd(TENANT, fdid, L2BD)
+
+ subnets[snet] = odl_gbp.get_subnet(TENANT, snid, fdid, snet, router)
+ odl_gbp.get_epg(TENANT, host['endpointGroup'])["network-domain"] = snid
+
+ odl_gbp.get_ep(TENANT,
+ host['endpointGroup'],
+ L3CTX,
+ re.sub(r'/\d+$', '', host['ip']),
+ L2BD,
+ host['mac'],
+ int(net.get(host['switch']).dpid), host['port'])
+
+ for contract in contracts:
+ odl_gbp.get_contract(TENANT,
+ contract['provider'], contract['consumer'],
+ contract['id'])
+
+ if args.policy:
+ odl_gbp.register_tenants(args.controller)
+
+ odl_gbp.register_eps(args.controller)
+
+ if net is not None:
+ mininet.cli.CLI(net)
+ finally:
+ if net is not None:
+ net.stop()