*/
public Collection<Subnet> resolveSubnets(NetworkDomainId id) {
Set<SubnetId> sset = new HashSet<>();
- HashSet<NetworkDomainId> visited = new HashSet<>();
+ HashSet<NetworkDomainId> visited = new HashSet<>();
while (id != null) {
if (visited.contains(id)) break;
visited.add(id);
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
*
* @return the
* {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3}
+ * @return {@link Collection} of the {@link EndpointL3}.
+ * Empty {@link Collection} if no {@link EndpointL3} is found.
*/
protected Collection<EndpointL3> getL3Endpoints() {
Endpoints endpoints = getEndpointsFromDataStore();
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxRegMatch;
import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;
import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;
import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxOutputRegAction;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
+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.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.Segmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
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.Ipv4MatchBuilder;
+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.NxmNxReg7;
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Preconditions;
+
/**
* Manage the table that assigns source endpoint group, bridge domain, and
* router domain to registers to be used by other tables.
@Override
public void sync(NodeId nodeId, OfWriter ofWriter) throws Exception {
- if (ctx.getSwitchManager().getExternalPorts(nodeId) == null) {
+ if (ctx.getSwitchManager().getExternalPorts(nodeId).isEmpty()) {
LOG.trace("No external ports found for node: {}", nodeId);
return;
}
// Default drop all
ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
+ /*
+ * When source address was translated to NAT address, it has to be figured out
+ * whether or not the traffic should be tagged since external interfaces are
+ * considered as trunk ports.
+ *
+ * Subnet to which NAT address belong have to be found so that
+ * corresponding L2FloodDomain can be resolved.
+ *
+ * If the L2FloodDomain contains Segmentation augmentation, a Flow is generated
+ * for applying VLAN tag against traffic with NAT IP as source address.
+ *
+ * Note: NetworkContainment of NAT EndpointL3 point's to subnet of original address.
+ * This is why subnet of NAT IP is resolved here.
+ */
+ Collection<EndpointL3> natL3Endpoints = ctx.getEndpointManager().getL3EndpointsWithNat();
+ if (natL3Endpoints != null) {
+ for (EndpointL3 natL3Ep : natL3Endpoints) {
+ IpAddress natIpAddress = Preconditions.checkNotNull(natL3Ep.getAugmentation(NatAddress.class),
+ "NAT address augmentation is missing for NAT endpoint: [{}].", natL3Ep.getKey())
+ .getNatAddress();
+ L2FloodDomain natEpl2Fd = resolveL2FloodDomainForIpv4Address(ctx.getTenant(natL3Ep.getTenant()),
+ Preconditions.checkNotNull(natIpAddress.getIpv4Address(),
+ "Endpoint {} does not have IPv4 address in NatAddress augmentation.", natL3Ep.getKey()));
+ if (natEpl2Fd != null && natEpl2Fd.getAugmentation(Segmentation.class) != null) {
+ Integer vlanId = natEpl2Fd.getAugmentation(Segmentation.class).getSegmentationId();
+ ofWriter.writeFlow(nodeId, TABLE_ID, buildPushVlanFlow(natIpAddress.getIpv4Address(), vlanId, 222));
+ }
+ }
+ }
+
+ /*
+ * Tagging should be also considered when traffic is routed or switched to external domain.
+ *
+ * If the L2FloodDomain of Endpoint contains Segmentation augmentation, a Flow
+ * for applying VLAN tag is generated. The flow matches against REG5 holding
+ * the L2FloodDomain and REG7 holding value of an external interface.
+ */
+ for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
+ L2FloodDomain l2Fd = ctx.getTenant(ep.getTenant()).resolveL2FloodDomain(ep.getNetworkContainment());
+ Segmentation segmentation = l2Fd.getAugmentation(Segmentation.class);
+ if (segmentation == null) {
+ continue;
+ }
+ Integer vlanId = segmentation.getSegmentationId();
+ for (Flow flow : buildPushVlanFlow(nodeId, OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, ep).getFdId(),
+ vlanId, 220)) {
+ ofWriter.writeFlow(nodeId, TABLE_ID, flow);
+ }
+ }
+
/*
* Default Egress flow. Other methods may write to this table to augment egress
* functionality, such as bypassing/utilising the NAT table, or ServiceFunctionChaining
*/
ofWriter.writeFlow(nodeId, TABLE_ID, defaultFlow());
+ }
+ static L2FloodDomain resolveL2FloodDomainForIpv4Address(IndexedTenant t, Ipv4Address ipv4Addr) {
+ Preconditions.checkNotNull(ipv4Addr);
+ if (t == null || t.getTenant() == null || t.getTenant().getForwardingContext() == null) {
+ return null;
+ }
+ List<Subnet> subnets = t.getTenant().getForwardingContext().getSubnet();
+ if (subnets != null) {
+ for (Subnet subnet : subnets) {
+ if (belongsToSubnet(ipv4Addr, subnet.getIpPrefix().getIpv4Prefix())) {
+ return t.resolveL2FloodDomain(subnet.getParent());
+ }
+ }
+ }
+ LOG.warn(
+ "No subnet for IPv4 address {} found in tenant {}!",
+ ipv4Addr.getValue(), t.getTenant().getId());
+ return null;
+ }
+
+ static boolean belongsToSubnet(Ipv4Address ipv4Address, Ipv4Prefix subnetPrefix) {
+ SubnetUtils su = new SubnetUtils(subnetPrefix.getValue());
+ SubnetInfo si = su.getInfo();
+ return si.isInRange(ipv4Address.getValue());
+ }
+
+ /**
+ * Generates a {@link Flow} for tagging VLAN traffic based on given arguments.
+ *
+ * @param ipv4Address source IPv4 address
+ * @param vlanId ID of VLAN tag to apply
+ * @param priority priority of the flow in the table
+ * @return {@link Flow} matching IPv4 source address, IPv4 ether-type and VLAN not set.
+ */
+ private Flow buildPushVlanFlow(Ipv4Address ipv4Address, Integer vlanId, int priority) {
+ // It is not needed here to match against external interfaces because
+ // we only use NAT when going to external networks.
+ Ipv4Prefix natIp = new Ipv4Prefix(ipv4Address.getValue() + "/32");
+ Match match = new MatchBuilder()
+ .setEthernetMatch(FlowUtils.ethernetMatch(null, null, Long.valueOf(FlowUtils.IPv4)))
+ .setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(natIp).build())
+ .setVlanMatch(FlowUtils.vlanMatch(0, false))
+ .build();
+ List<ActionBuilder> pushVlanActions = new ArrayList<>();
+ pushVlanActions.addAll(FlowUtils.pushVlanActions(vlanId));
+ pushVlanActions.add(new ActionBuilder().setOrder(0).setAction(nxOutputRegAction(NxmNxReg7.class)));
+ FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "external_nat_push_vlan", match);
+ return base().setPriority(priority)
+ .setId(flowid)
+ .setMatch(match)
+ .setInstructions(FlowUtils.instructions(applyActionIns(pushVlanActions)))
+ .build();
+ }
+
+ /**
+ * Generates a {@link Flow} for tagging VLAN traffic based on given arguments.
+ *
+ * @param nodeId of {@link Node} from which external interfaces are resolved
+ * @param fdId {@link L2FloodDomain} ordinal to match against
+ * @param vlanId applied to the traffic
+ * @param priority of flow in the table
+ * @return {@link List} of {@link Flow} matching {@link L2FloodDomain} in REG5,
+ * external interfaces of {@link Node} in REG7 and VLAN not set.
+ */
+ private List<Flow> buildPushVlanFlow(NodeId nodeId, int fdId, Integer vlanId, int priority) {
+ List<Flow> flows = new ArrayList<>();
+ for (Long portNum : ctx.getSwitchManager().getExternalPortNumbers(nodeId)) {
+ MatchBuilder mb = new MatchBuilder().setVlanMatch(FlowUtils.vlanMatch(0, false));
+ addNxRegMatch(mb, RegMatch.of(NxmNxReg7.class, BigInteger.valueOf(portNum).longValue()),
+ RegMatch.of(NxmNxReg5.class, Long.valueOf(fdId)));
+ Match match = mb.build();
+ List<ActionBuilder> pushVlanActions = new ArrayList<>();
+ pushVlanActions.addAll(FlowUtils.pushVlanActions(vlanId));
+ pushVlanActions.add(new ActionBuilder().setOrder(0).setAction(nxOutputRegAction(NxmNxReg7.class)));
+ FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "external_push_vlan", match);
+ flows.add(base().setPriority(priority)
+ .setId(flowid)
+ .setMatch(match)
+ .setInstructions(FlowUtils.instructions(applyActionIns(pushVlanActions)))
+ .build());
+ }
+ return flows;
}
private Flow defaultFlow() {
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.PopVlanActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
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.SetNwDstActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
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.pop.vlan.action._case.PopVlanActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
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.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
import org.opendaylight.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.ethernet.match.fields.EthernetSourceBuilder;
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.model.match.types.rev131026.match.VlanMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
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;
* IPv6 ethertype
*/
public static final Long IPv6 = Long.valueOf(0x86DD);
+ /**
+ * VLAN ethertype
+ */
+ public static final Integer VLAN = Integer.valueOf(0x8100);
/**
* Creates an Instance Identifier (path) for node with specified id
.build();
}
+ public static VlanMatch vlanMatch(int vlanId, boolean vlanIdPresent) {
+ return new VlanMatchBuilder().setVlanId(
+ new VlanIdBuilder().setVlanId(new VlanId(vlanId)).setVlanIdPresent(vlanIdPresent).build()).build();
+ }
+
+ public static List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder> pushVlanActions(int vlanId) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder> actions = new ArrayList<>();
+ actions.add(new ActionBuilder().setAction(pushVlanAction()).setOrder(0));
+ actions.add(new ActionBuilder().setAction(setVlanId(vlanId)).setOrder(1));
+ return actions;
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction popVlanInstruction(
+ int order) {
+ List<ActionBuilder> actionBuilders = new ArrayList<>();
+ actionBuilders.add(new ActionBuilder().setAction(popVlanAction()).setOrder(0));
+ return new InstructionBuilder().setInstruction(
+ new ApplyActionsCaseBuilder().setApplyActions(
+ new ApplyActionsBuilder().setAction(actionList(actionBuilders)).build()).build())
+ .setOrder(order)
+ .build();
+ }
+
public static Action setIpv4DstAction(Ipv4Address ipAddress) {
Ipv4Builder ipDest = new Ipv4Builder();
Ipv4Prefix prefixdst = new Ipv4Prefix(new Ipv4Prefix(ipAddress.getValue() + "/32"));
return emb.build();
}
+ private static Action pushVlanAction() {
+ return new PushVlanActionCaseBuilder().setPushVlanAction(
+ new PushVlanActionBuilder().setEthernetType(VLAN).build()).build();
+ }
+
+ private static Action popVlanAction() {
+ return new PopVlanActionCaseBuilder().setPopVlanAction(new PopVlanActionBuilder().build()).build();
+ }
+
+ private static Action setVlanId(int vlanId) {
+ return new SetVlanIdActionCaseBuilder().setSetVlanIdAction(
+ new SetVlanIdActionBuilder().setVlanId(new VlanId(vlanId)).build()).build();
+ }
+
private static List<ExtensionList> getExistingGeneralAugMatchNodesNodeTableFlow(MatchBuilder match) {
ArrayList<ExtensionList> extensions = new ArrayList<>();
if (match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class) != null) {
import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIPv4Action;
import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.outputAction;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
+import org.antlr.v4.runtime.misc.Array2DHashSet;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.groupbasedpolicy.dto.EgKey;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
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.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
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.group.types.rev131018.group.buckets.BucketBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.Segmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
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.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
EndpointFwdCtxOrdinals localEpFwdCtxOrds =
OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, localEp);
if (localEpFwdCtxOrds == null) {
- LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", localEp);
+ LOG.info("getEndpointFwdCtxOrdinals is null for EP {}", localEp);
continue;
}
ofWriter.writeBucket(nodeId, gid, bb.build());
}
}
+ // TODO broadcasts are not separated by EPG between endpoints on the same node
OfOverlayContext ofc = localEp.getAugmentation(OfOverlayContext.class);
if (EndpointManager.isExternal(localEp, ctx.getTenant(localEp.getTenant()).getExternalImplicitGroups()))
continue;
LOG.warn("Could not parse port number {}", ofc.getNodeConnectorId(), e);
continue;
}
-
Action output = outputAction(ofc.getNodeConnectorId());
- BucketBuilder bb = new BucketBuilder().setBucketId(new BucketId(Long.valueOf(bucketId)))
- .setAction(actionList(output));
+ BucketBuilder bb = new BucketBuilder().setBucketId(new BucketId(Long.valueOf(bucketId))).setAction(
+ FlowUtils.actionList(output));
ofWriter.writeBucket(nodeId, gid, bb.build());
+
+ // if boradcast exceeds internal domain
+ for (Endpoint extEp : ctx.getEndpointManager().getExtEpsNoLocForGroup(epg)) {
+ if (extEp.getNetworkContainment() != null
+ && extEp.getNetworkContainment().equals(localEp.getNetworkContainment())) {
+ L2FloodDomain l2Fd = ctx.getTenant(extEp.getTenant()).resolveL2FloodDomain(
+ extEp.getNetworkContainment());
+ if (l2Fd != null) {
+ Segmentation segmentation = l2Fd.getAugmentation(Segmentation.class);
+ // external endpoints do not have location augmentation
+ // however they are beyond external ports
+ for (NodeConnectorId extNcId : ctx.getSwitchManager().getExternalPorts(nodeId)) {
+ try {
+ bucketId = getOfPortNum(extNcId);
+ } catch (NumberFormatException e) {
+ LOG.warn("Could not parse external port number {}", extNcId, e);
+ continue;
+ }
+ ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder>
+ actionList = new ArrayList<>();
+ if (segmentation != null) {
+ Integer vlanId = segmentation.getSegmentationId();
+ actionList.addAll(FlowUtils.pushVlanActions(vlanId));
+ actionList.add(new ActionBuilder().setOrder(2).setAction(outputAction(extNcId)));
+ } else {
+ actionList.add(new ActionBuilder().setOrder(0).setAction(outputAction(extNcId)));
+ }
+ bb.setBucketId(new BucketId(Long.valueOf(bucketId))).setAction(
+ FlowUtils.actionList(actionList));
+ ofWriter.writeBucket(nodeId, gid, bb.build());
+ }
+ }
+ }
+ }
}
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
@Override
public void sync(NodeId nodeId, OfWriter ofWriter) throws Exception {
- ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
+ // TODO for consideration: default instruction is goto next table because when matching against eth type 0x8100
+ // in PortSecurity, it's not possible to match against IPv4 addresses (only inf eth type would be 0x800)
+ // We can't determine just from L2 layer if traffic should be passed from PortSecurity here to IngressNat or to
+ // SourceMapper. Various 802.1q encapsulated IPs can pass through external ports - NATed or not NATed, remote
+ // or directly connected.
+ // All external ingress traffic is currently passed here and if no match is foud - no NAT is performed
+ // and processing continues in SourceMapper.
+ Flow flow = base()
+ .setTableId(TABLE_ID)
+ .setPriority(1)
+ .setInstructions(FlowUtils.instructions(FlowUtils.gotoTableIns(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER())))
+ .setId(FlowIdUtils.newFlowId("gotoSourceMapper"))
+ .build();
+ ofWriter.writeFlow(nodeId, TABLE_ID, flow);
// TODO Bug 3546 - Difficult: External port is unrelated to Tenant, L3C, L2BD..
import java.util.Collections;
import java.util.List;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Set;
import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+
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.policy.ExternalImplicitGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.Segmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
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.match.Layer3Match;
if (tunnelIf != null)
ofWriter.writeFlow(nodeId, TABLE_ID, allowFromPort(tunnelIf));
- // Allow traffic from tunnel ports
- //TODO Bug 3546 - Difficult: External port is unrelated to Tenant, L3C, L2BD..
-
- Set<NodeConnectorId> external =
- ctx.getSwitchManager().getExternalPorts(nodeId);
- for (NodeConnectorId extIf : external) {
- ofWriter.writeFlow(nodeId, TABLE_ID, allowFromExternalPort(extIf));
- }
-
// Default drop all
ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(111), FlowUtils.IPv4, TABLE_ID));
ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(112), FlowUtils.IPv6, TABLE_ID));
+ Set<TenantId> tenantIds = new HashSet<>();
for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
if (ofc == null || ofc.getNodeConnectorId() == null) {
continue;
}
+ tenantIds.add(ep.getTenant());
Set<ExternalImplicitGroup> eigs = getExternalImplicitGroupsForTenant(ep.getTenant());
if (EndpointManager.isInternal(ep, eigs)) {
// Allow layer 3 traffic (ARP and IP) with the correct
}
}
}
+
+ for (TenantId tenantId : tenantIds) {
+ for (NodeConnectorId nc : ctx.getSwitchManager().getExternalPorts(nodeId)) {
+ // TODO Bug 3546 - Difficult: External port is unrelated to Tenant, L3C, L2BD..
+ for (Flow flow : popVlanTagsOnExternalPort(nc, tenantId, 210)) {
+ // tagged frames have to be untagged when entering policy domain
+ ofWriter.writeFlow(nodeId, TABLE_ID, flow);
+ }
+ // allowing untagged frames entering policy domain
+ ofWriter.writeFlow(nodeId, TABLE_ID, allowFromExternalPort(nc, 200));
+ }
+ }
}
private Set<ExternalImplicitGroup> getExternalImplicitGroupsForTenant(TenantId tenantId) {
FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "allow", match);
FlowBuilder flowb = base()
.setId(flowid)
- .setPriority(Integer.valueOf(200))
+ .setPriority(Integer.valueOf(300))
.setMatch(match)
.setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()));
return flowb.build();
}
- private Flow allowFromExternalPort(NodeConnectorId port) {
- Match match = new MatchBuilder()
- .setInPort(port)
- .build();
- FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "allowExternal", match);
- FlowBuilder flowb = base()
- .setId(flowid)
- .setPriority(Integer.valueOf(200))
- .setMatch(match)
- .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_INGRESS_NAT()));
- return flowb.build();
- }
-
private Flow l2flow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
Match match = new MatchBuilder()
.setEthernetMatch(
.setMatch(match)
.setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()))
.build();
-
return flow;
}
ofWriter.writeFlow(nodeId, TABLE_ID,flow);
}
}
+
+ private Flow allowFromExternalPort(NodeConnectorId nc, Integer priority) {
+ Match match = new MatchBuilder().setInPort(nc).build();
+ FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "allowExternal", match);
+ FlowBuilder flowb = base().setId(flowid)
+ .setPriority(Integer.valueOf(priority))
+ .setMatch(match)
+ .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_INGRESS_NAT()));
+ return flowb.build();
+ }
+
+ /**
+ * Pops VLAN tag for inbound traffic.
+ *
+ * @param nc should be external for now
+ * @param tenantId of {@link Tenant} from which {@link L2FloodDomain}s are read from which VLAN IDs are resolved.
+ * @param priority of flows in the table
+ * @return {@link Flow}s which match on ingress port, and VLAN ID to pop.
+ * {@link GoToTable} Instructions are set to INGRESS NAT table.
+ */
+ private List<Flow> popVlanTagsOnExternalPort(NodeConnectorId nc, TenantId tenantId, Integer priority) {
+ List<Flow> flows = new ArrayList<>();
+ for(L2FloodDomain l2Fd : ctx.getTenant(tenantId).getTenant().getForwardingContext().getL2FloodDomain()) {
+ Segmentation segmentation = l2Fd.getAugmentation(Segmentation.class);
+ if (segmentation != null) {
+ Integer vlanId = segmentation.getSegmentationId();
+ flows.add(buildPopVlanFlow(nc, vlanId, priority));
+ }
+ }
+ return flows;
+ }
+
+ private Flow buildPopVlanFlow(NodeConnectorId nc, Integer vlanId, int priority) {
+ Match match = new MatchBuilder()
+ .setVlanMatch(FlowUtils.vlanMatch(vlanId, true))
+ .setInPort(nc)
+ .build();
+ List<Instruction> instructions = new ArrayList<>();
+ instructions.add(FlowUtils.popVlanInstruction(0));
+ instructions.add(new InstructionBuilder().setOrder(1)
+ // TODO for now matches on external flows are passed to ingress nat table
+ .setInstruction(FlowUtils.gotoTableIns(ctx.getPolicyManager().getTABLEID_INGRESS_NAT()))
+ .build());
+ FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "allowExternalPopVlan", match);
+ return base().setPriority(priority)
+ .setId(flowid)
+ .setMatch(match)
+ .setInstructions(new InstructionsBuilder().setInstruction(instructions).build())
+ .build();
+ }
}
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.getOfPortNum;
import java.util.Collection;
import java.util.Collections;
import javax.annotation.Nullable;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchListener;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
return ImmutableSet.copyOf(state.externalPorts);
}
+ public Set<Long> getExternalPortNumbers(NodeId nodeId) {
+ Set<Long> extPortNumbers = new HashSet<>();
+ for(NodeConnectorId nc : getExternalPorts(nodeId)) {
+ long portNum;
+ try {
+ portNum = getOfPortNum(nc);
+ } catch (NumberFormatException ex) {
+ LOG.warn("Could not parse port number {}", nc, ex);
+ return null;
+ }
+ extPortNumbers.add(portNum);
+ }
+ return extPortNumbers;
+ }
+
public synchronized Collection<NodeConnectorId> getTunnelPorts(NodeId nodeId) {
Collection<NodeConnectorId> ncIds = new HashSet<>();
SwitchState state = switches.get(nodeId);
import gbp-common {prefix gbp-common;}
import endpoint {prefix endpoint;}
+ import policy {prefix policy;}
description
"This module defines the group-based policy ofoverlay renderer model.";
uses endpoint-location;
}
+ augment "/policy:tenants/policy:tenant/policy:forwarding-context/policy:l2-flood-domain" {
+ ext:augment-identifier "segmentation";
+ leaf segmentation-id {
+ description "Logical segmentation of an l2-flood-domain, e.g. by using VLANs.";
+ type uint16 {
+ range "1 .. 4095";
+ }
+ }
+ }
+
augment "/inv:nodes/inv:node" {
ext:augment-identifier "of-overlay-node-config";
list tunnel {
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
/**
* Class for mocking up endpoints for unit tests
*/
public class MockEndpointManager extends EndpointManager {
+ private Map<EndpointL3Key, EndpointL3> endpointsL3 = new HashMap<>();
+
public MockEndpointManager() {
super(null, null, null, null, null);
}
public void addEndpoint(Endpoint ep) {
processEndpoint(null, ep);
}
+
+ public void addL3Endpoint(EndpointL3 l3Ep) {
+ endpointsL3.put(l3Ep.getKey(), l3Ep);
+ }
+
+ @Override
+ protected Collection<EndpointL3> getL3Endpoints() {
+ return endpointsL3.values();
+ }
}
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
+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.endpoint.rev140421.endpoints.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-public class ExternalMapperTest {
+import com.google.common.collect.ImmutableSet;
+
+public class ExternalMapperTest extends FlowTableTest {
private ExternalMapper mapper;
- private OfContext ctx;
private short tableId;
private NodeId nodeId;
private OfWriter ofWriter;
- private SwitchManager switchManager;
+
+ private NatAddress natAddr = new NatAddressBuilder()
+ .setNatAddress(new IpAddress(new Ipv4Address("192.168.111.52")))
+ .build();
+
+ private EndpointL3 natL3Ep = new EndpointL3Builder()
+ .setTenant(tid)
+ .setL3Context(l3c)
+ .setIpAddress(new IpAddress(new Ipv4Address("10.0.0.3")))
+ .addAugmentation(NatAddress.class, natAddr)
+ .build();
+
+ private Endpoint l2Ep = new EndpointBuilder()
+ .setTenant(tid)
+ .setMacAddress(new MacAddress("00:00:00:00:00:03"))
+ .setL2Context(bd)
+ .setNetworkContainment(sub)
+ .setEndpointGroup(eg)
+ .build();
@Before
public void initialisation() {
- ctx = mock(OfContext.class);
- tableId = 5;
+ initCtx();
+ tableId = 6;
nodeId = mock(NodeId.class);
ofWriter = mock(OfWriter.class);
- switchManager = mock(SwitchManager.class);
- when(ctx.getSwitchManager()).thenReturn(switchManager);
-
mapper = new ExternalMapper(ctx, tableId);
}
@Test
public void syncTest() throws Exception {
- NodeConnectorId nodeConnectorId = mock(NodeConnectorId.class);
- Set<NodeConnectorId> externalPorts = new HashSet<NodeConnectorId>(Arrays.asList(nodeConnectorId));
- when(switchManager.getExternalPorts(nodeId)).thenReturn(externalPorts);
-
+ ctx.addTenant(baseTenant().build());
+ endpointManager.addL3Endpoint(natL3Ep);
+ l2Ep = new EndpointBuilder(l2Ep)
+ .addAugmentation(OfOverlayContext.class,new OfOverlayContextBuilder()
+ .setNodeId(nodeId)
+ .build())
+ .build();
+ endpointManager.addEndpoint(l2Ep);
+ switchManager.addSwitch(nodeId,null,ImmutableSet.<NodeConnectorId>of(new NodeConnectorId("openflow:1:1")), null);
mapper.sync(nodeId, ofWriter);
- verify(ofWriter, times(2)).writeFlow(any(NodeId.class), any(Short.class), any(Flow.class));
+ verify(ofWriter, times(4)).writeFlow(any(NodeId.class), any(Short.class), any(Flow.class));
}
@Test
public void syncTestNoExternalPorts() throws Exception {
- when(switchManager.getExternalPorts(nodeId)).thenReturn(null);
-
mapper.sync(nodeId, ofWriter);
verify(ofWriter, never()).writeFlow(any(NodeId.class), any(Short.class), any(Flow.class));
}
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.groupbasedpolicy.dto.EgKey;
import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
+import org.opendaylight.groupbasedpolicy.dto.PolicyInfo;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.CheckedFuture;
public class GroupTableTest {
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.Segmentation;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.SegmentationBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRefBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContextBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.PolicyBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomainBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ContractBuilder;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroupBuilder;\r
L3ContextId l3c = new L3ContextId("2cf51ee4-e996-467e-a277-2d380334a91d");\r
L2BridgeDomainId bd = new L2BridgeDomainId("c95182ba-7807-43f8-98f7-6c7c720b7639");\r
L2FloodDomainId fd = new L2FloodDomainId("98e1439e-52d2-46f8-bd69-5136e6088771");\r
+ L2FloodDomainId ext_fd = new L2FloodDomainId("d8024f7a-b83e-11e5-9912-ba0be0483c18");\r
SubnetId sub = new SubnetId("4fcf8dfc-53b5-4aef-84d3-6b5586992fcb");\r
SubnetId sub2 = new SubnetId("c285a59f-fcb8-42e6-bf29-87ea522fd626");\r
SubnetId sub3 = new SubnetId("a0380d52-2a25-48ef-882c-a4d4cd9e00ec");\r
+ SubnetId ext_sub = new SubnetId("8da17ad9-3261-4dc9-bcff-928a2f73cce7");\r
TenantId tid = new TenantId("1118c691-8520-47ad-80b8-4cf5e3fe3302");\r
EndpointGroupId eg = new EndpointGroupId("36dec84a-08c7-497b-80b6-a0035af72a12");\r
EndpointGroupId eg2 = new EndpointGroupId("632e5e11-7988-4eb5-8fe6-6c182d890276");\r
.setL3Context(ImmutableList.of(new L3ContextBuilder().setId(l3c).build()))\r
.setL2BridgeDomain(\r
ImmutableList.of(new L2BridgeDomainBuilder().setId(bd).setParent(l3c).build()))\r
- .setL2FloodDomain(ImmutableList.of(new L2FloodDomainBuilder().setId(fd).setParent(bd).build()))\r
+ .setL2FloodDomain(ImmutableList.of(\r
+ new L2FloodDomainBuilder()\r
+ .setId(fd)\r
+ .setParent(bd)\r
+ .addAugmentation(Segmentation.class,\r
+ new SegmentationBuilder()\r
+ .setSegmentationId(Integer.valueOf(216))\r
+ .build())\r
+ .build(),\r
+ new L2FloodDomainBuilder()\r
+ .setId(ext_fd)\r
+ .addAugmentation(Segmentation.class,\r
+ new SegmentationBuilder()\r
+ .setSegmentationId(Integer.valueOf(2016))\r
+ .build())\r
+ .build()))\r
.setSubnet(ImmutableList.of(\r
new SubnetBuilder().setId(sub2)\r
.setParent(fd)\r
.setParent(bd)\r
.setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.2.0/24")))\r
.setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.2.1")))\r
+ .build(),\r
+ new SubnetBuilder()\r
+ .setId(ext_sub)\r
+ .setIpPrefix(new IpPrefix(new Ipv4Prefix("192.168.111.0/24")))\r
+ .setParent(ext_fd)\r
.build()))\r
- .build());\r
+ .build());\r
}\r
\r
protected ContractBuilder baseContract(List<Subject> subjects) {\r
protected static final Logger LOG =\r
LoggerFactory.getLogger(PortSecurityTest.class);\r
\r
+ private Endpoint ep = localEP()\r
+ .setL3Address(ImmutableList.of(new L3AddressBuilder()\r
+ .setIpAddress(new IpAddress(new Ipv4Address("10.10.10.10")))\r
+ .build(),\r
+ new L3AddressBuilder()\r
+ .setIpAddress(new IpAddress(new Ipv6Address("2001:db8:85a3::8a2e:370:7334")))\r
+ .build()))\r
+ .build();\r
@Override\r
@Before\r
public void setup() throws Exception {\r
for (Flow f : fm.getTableForNode(nodeId, ctx.getPolicyManager().getTABLEID_PORTSECURITY()).getFlow()) {\r
flowMap.put(f.getId().getValue(), f);\r
if (f.getMatch() != null && f.getMatch().getInPort() != null &&\r
- ncs.contains(f.getMatch().getInPort().getValue())) {\r
+ (ncs.contains(f.getMatch().getInPort().getValue()))) {\r
assertTrue(f.getInstructions().equals(\r
FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_INGRESS_NAT()))\r
|| f.getInstructions().equals(\r
count += 1;\r
}\r
}\r
- assertEquals(2, count);\r
+ assertEquals(1, count);\r
int numberOfFlows = fm.getTableForNode(nodeId, ctx.getPolicyManager().getTABLEID_PORTSECURITY()).getFlow().size();\r
fm = dosync(flowMap);\r
assertEquals(numberOfFlows, fm.getTableForNode(nodeId, ctx.getPolicyManager().getTABLEID_PORTSECURITY()).getFlow().size());\r
\r
@Test\r
public void testL3() throws Exception {\r
- Endpoint ep = localEP()\r
- .setL3Address(ImmutableList.of(new L3AddressBuilder()\r
- .setIpAddress(new IpAddress(new Ipv4Address("10.10.10.10")))\r
- .build(),\r
- new L3AddressBuilder()\r
- .setIpAddress(new IpAddress(new Ipv6Address("2001:db8:85a3::8a2e:370:7334")))\r
- .build()))\r
- .build();\r
-\r
endpointManager.addEndpoint(ep);\r
\r
OfWriter fm = dosync(null);\r
fm = dosync(flowMap);\r
assertEquals(numberOfFlows, fm.getTableForNode(nodeId, ctx.getPolicyManager().getTABLEID_PORTSECURITY()).getFlow().size());\r
}\r
+\r
+ @Test\r
+ public void testExternal() throws Exception {\r
+ endpointManager.addEndpoint(ep);\r
+ switchManager.addSwitch(\r
+ new NodeId("openflow:12"),\r
+ new NodeConnectorId("openflow:12:1"),\r
+ ImmutableSet.of(new NodeConnectorId("openflow:12:2")),\r
+ new OfOverlayNodeConfigBuilder().setTunnel(\r
+ ImmutableList.of(new TunnelBuilder().setTunnelType(TunnelTypeVxlan.class)\r
+ .setNodeConnectorId(new NodeConnectorId("openflow:12:1"))\r
+ .build())).build());\r
+ ctx.addTenant(baseTenant().build());\r
+ OfWriter fm = dosync(null);\r
+ }\r
}\r