/*
* 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.math.BigInteger;
import java.util.List;
import java.util.Map;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
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.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.flow.types.rev131026.flow.MatchBuilder;
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.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.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.
* @author readams
*/
public class SourceMapper extends FlowTable {
protected static final Logger LOG =
LoggerFactory.getLogger(SourceMapper.class);
public static final short TABLE_ID = 1;
public SourceMapper(OfTable.OfTableCtx ctx) {
super(ctx);
}
@Override
public short getTableId() {
return TABLE_ID;
}
@Override
public void sync(ReadWriteTransaction t,
InstanceIdentifier
tiid,
Map flowMap,
NodeId nodeId, PolicyInfo policyInfo,
Dirty dirty) throws Exception {
dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
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,
egId, bdId, fdId, l3Id);
}
}
}
}
private void syncEP(ReadWriteTransaction t,
InstanceIdentifier tiid,
Map flowMap,
PolicyInfo policyInfo,
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
List conds = ctx.epManager.getCondsForEndpoint(e);
ConditionGroup cg =
policyInfo.getEgCondGroup(new EgKey(e.getTenant(),
e.getEndpointGroup()),
conds);
int cgId = ctx.policyManager.getCondGroupOrdinal(cg);
FlowId flowid = new FlowId(new StringBuilder()
.append(ofc.getNodeConnectorId().getValue())
.append("|")
.append(e.getMacAddress().getValue())
.append("|")
.append(egId)
.append("|")
.append(bdId)
.append("|")
.append(fdId)
.append("|")
.append(l3Id)
.append("|")
.append(cgId)
.toString());
if (visit(flowMap, flowid.getValue())) {
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(ethernetMatch(e.getMacAddress(),
null, null))
.setInPort(ofc.getNodeConnectorId())
.build())
.setInstructions(instructions(applyActionIns(segReg,
scgReg,
bdReg,
fdReg,
vrfReg),
gotoTableIns((short)(TABLE_ID + 1))));
writeFlow(t, tiid, flowb.build());
}
}
}