2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
11 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxTunIdMatch;
12 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;
13 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.ethernetMatch;
14 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.gotoTableIns;
15 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;
16 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadRegAction;
17 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIdAction;
19 import java.math.BigInteger;
20 import java.util.Collections;
21 import java.util.HashSet;
24 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
25 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
26 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
27 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
28 import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
29 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 import com.google.common.collect.Sets;
52 * Manage the table that assigns source endpoint group, bridge domain, and
53 * router domain to registers to be used by other tables.
55 public class SourceMapper extends FlowTable {
57 protected static final Logger LOG = LoggerFactory.getLogger(SourceMapper.class);
59 // TODO Li alagalah Improve UT coverage for this class.
60 public static final short TABLE_ID = 1;
62 public SourceMapper(OfContext ctx) {
67 public short getTableId() {
72 public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) throws Exception {
74 flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null));
76 for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
77 OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
78 if (ofc != null && ofc.getNodeConnectorId() != null
79 && (ofc.getLocationType() == null || LocationType.Internal.equals(ofc.getLocationType()))
80 && ep.getTenant() != null && (ep.getEndpointGroup() != null || ep.getEndpointGroups() != null)) {
82 IndexedTenant tenant = ctx.getPolicyResolver().getTenant(ep.getTenant());
86 EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, ep);
87 EgKey sepg = new EgKey(ep.getTenant(), ep.getEndpointGroup());
89 createRemoteTunnels(flowMap, nodeId, ep, policyInfo, epFwdCtxOrds);
92 * Sync the local EP information.
94 syncEP(flowMap, policyInfo, nodeId, ep, ofc, sepg, epFwdCtxOrds);
99 private void createRemoteTunnels(FlowMap flowMap, NodeId nodeId, Endpoint ep, PolicyInfo policyInfo,
100 EndpointFwdCtxOrdinals epFwdCtxOrds) throws Exception {
101 Set<EgKey> epgs = new HashSet<>();
103 // Get EPGs and add to Set to remove duplicates
104 // TODO alagalah Li: test EndpointManager.getEgKeys
105 if (ep.getEndpointGroup() != null) {
106 epgs.add(new EgKey(ep.getTenant(), ep.getEndpointGroup()));
108 if (ep.getEndpointGroups() != null) {
109 for (EndpointGroupId epgId : ep.getEndpointGroups()) {
110 epgs.add(new EgKey(ep.getTenant(), epgId));
114 // Create tunnels on remote Nodes that may talk to us.
115 for (EgKey epg : epgs) {
116 Set<EgKey> peers = Sets.union(Collections.singleton(epg), policyInfo.getPeers(epg));
117 for (EgKey peer : peers) {
118 for (NodeId remoteNodeId : ctx.getEndpointManager().getNodesForGroup(peer)) {
120 // Please do not check for remote v local nodeID, we need local to local tunnels
121 // in the case of chaining - The Great Dr Sunal.
122 NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(remoteNodeId);
123 if (tunPort == null) {
124 LOG.trace("No tunnel port for tunnel in SourceMapper between local:{} and remote:{}",
125 nodeId.getValue(), remoteNodeId.getValue());
128 flowMap.writeFlow(remoteNodeId, TABLE_ID, createTunnelFlow(tunPort, epFwdCtxOrds));
129 flowMap.writeFlow(remoteNodeId, TABLE_ID, createBroadcastFlow(tunPort, epFwdCtxOrds));
135 private Flow createBroadcastFlow(NodeConnectorId tunPort, EndpointFwdCtxOrdinals epFwdCtxOrds) {
137 int fdId = epFwdCtxOrds.getFdId();
139 FlowId flowid = new FlowId(new StringBuilder().append(tunPort.getValue())
145 MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
146 addNxTunIdMatch(mb, fdId);
148 // set condition group register to all ones to
150 // policy enforcement
152 * TODO: This breaks distributed policy enforcement
153 * especially wrt multi-action. BAD. Must be addressed
154 * (this is why we can't have nice things).
155 * This can be fixed with new tunnelId ordinal in
159 Action fdReg = nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(fdId));
161 FlowBuilder flowb = base().setId(flowid)
162 .setPriority(Integer.valueOf(150))
163 .setMatch(mb.build())
164 .setInstructions(instructions(applyActionIns(fdReg), gotoTableIns((short) (TABLE_ID + 1))));
165 return flowb.build();
168 private Flow createTunnelFlow(NodeConnectorId tunPort, EndpointFwdCtxOrdinals epFwdCtxOrds) {
169 // ... this is a remote node.
171 int egId = epFwdCtxOrds.getEpgId();
172 int bdId = epFwdCtxOrds.getBdId();
173 int fdId = epFwdCtxOrds.getFdId();
174 int l3Id = epFwdCtxOrds.getL3Id();
175 int tunnelId = epFwdCtxOrds.getTunnelId();
177 FlowId flowid = new FlowId(new StringBuilder().append(tunPort.getValue())
190 MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
191 addNxTunIdMatch(mb, tunnelId);
192 Action segReg = nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(egId));
193 // set condition group register to all ones to
195 // policy enforcement
197 * TODO: This breaks distributed policy enforcement
198 * especially wrt multi-action. BAD. Must be addressed
199 * (this is why we can't have nice things).
200 * This can be fixed with new tunnelId ordinal in
203 Action scgReg = nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(0xffffff));
204 Action bdReg = nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(bdId));
205 Action fdReg = nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(fdId));
206 Action vrfReg = nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(l3Id));
207 FlowBuilder flowb = base().setId(flowid)
208 .setPriority(Integer.valueOf(150))
209 .setMatch(mb.build())
211 instructions(applyActionIns(segReg, scgReg, bdReg, fdReg, vrfReg),
212 gotoTableIns((short) (TABLE_ID + 1))));
213 return flowb.build();
216 private void syncEP(FlowMap flowMap, PolicyInfo policyInfo, NodeId nodeId, Endpoint ep, OfOverlayContext ofc,
217 EgKey egKey, EndpointFwdCtxOrdinals epFwdCtxOrds) throws Exception {
219 // TODO alagalah Li/Be: We should also match on EndpointL3 with the appropriate
220 // network containment. This would solve a lot of problems and prepare for EndpointL3 RPC.
222 int egId = epFwdCtxOrds.getEpgId();
223 int bdId = epFwdCtxOrds.getBdId();
224 int fdId = epFwdCtxOrds.getFdId();
225 int l3Id = epFwdCtxOrds.getL3Id();
226 int cgId = epFwdCtxOrds.getCgId();
227 int tunnelId = epFwdCtxOrds.getTunnelId();
229 FlowId flowid = new FlowId(new StringBuilder().append(ofc.getNodeConnectorId().getValue())
231 .append(ep.getMacAddress().getValue())
243 Action segReg = nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(egId));
244 Action scgReg = nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(cgId));
245 Action bdReg = nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(bdId));
246 Action fdReg = nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(fdId));
247 Action vrfReg = nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(l3Id));
248 Action tunIdAction = nxLoadTunIdAction(BigInteger.valueOf(tunnelId), false);
250 FlowBuilder flowb = base().setPriority(Integer.valueOf(100))
253 new MatchBuilder().setEthernetMatch(ethernetMatch(ep.getMacAddress(), null, null))
254 .setInPort(ofc.getNodeConnectorId())
257 instructions(applyActionIns(segReg, scgReg, bdReg, fdReg, vrfReg,tunIdAction),
258 gotoTableIns((short) (TABLE_ID + 1))));
259 flowMap.writeFlow(nodeId, TABLE_ID, flowb.build());