fda93f5cd15c1e0c9fe58b839f30c5f95d770574
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / flow / SourceMapper.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
10
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;
18
19 import java.math.BigInteger;
20 import java.util.Collections;
21 import java.util.HashSet;
22 import java.util.Map;
23 import java.util.Set;
24
25 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
26 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
27 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
28 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
29 import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
30 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 import com.google.common.collect.Sets;
55
56 /**
57  * Manage the table that assigns source endpoint group, bridge domain, and
58  * router domain to registers to be used by other tables.
59  */
60 public class SourceMapper extends FlowTable {
61
62     protected static final Logger LOG = LoggerFactory.getLogger(SourceMapper.class);
63
64     // TODO Li alagalah Improve UT coverage for this class.
65     public static short TABLE_ID;
66
67     public SourceMapper(OfContext ctx, short tableId) {
68         super(ctx);
69         TABLE_ID = tableId;
70     }
71
72     @Override
73     public short getTableId() {
74         return TABLE_ID;
75     }
76
77     @Override
78     public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) throws Exception {
79
80         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
81
82         // Handle case where packets from from External
83         for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
84             OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
85
86             IndexedTenant tenant = ctx.getPolicyResolver().getTenant(ep.getTenant());
87             if (tenant == null)
88                 continue;
89
90             EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, ep);
91             if (epFwdCtxOrds == null) {
92                 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", ep);
93                 continue;
94             }
95
96             createRemoteTunnels(flowMap, nodeId, ep, policyInfo, epFwdCtxOrds);
97
98             if (ep.getTenant() == null || (ep.getEndpointGroup() == null && ep.getEndpointGroups() == null)) {
99                 continue;
100             }
101
102             if (ofc != null && ofc.getNodeConnectorId() != null
103                     && (ofc.getLocationType() == null || LocationType.Internal.equals(ofc.getLocationType()))) {
104                 /**
105                  * Sync the local EP information.
106                  */
107                 syncEP(flowMap, nodeId, ep, ofc.getNodeConnectorId(), epFwdCtxOrds);
108             }
109         }
110     }
111
112     private void createRemoteTunnels(FlowMap flowMap, NodeId nodeId, Endpoint ep, PolicyInfo policyInfo,
113             EndpointFwdCtxOrdinals epFwdCtxOrds) throws Exception {
114         Set<EgKey> epgs = new HashSet<>();
115
116         // Get EPGs and add to Set to remove duplicates
117         // TODO alagalah Li: test EndpointManager.getEgKeys
118         if (ep.getEndpointGroup() != null) {
119             epgs.add(new EgKey(ep.getTenant(), ep.getEndpointGroup()));
120         }
121         if (ep.getEndpointGroups() != null) {
122             for (EndpointGroupId epgId : ep.getEndpointGroups()) {
123                 epgs.add(new EgKey(ep.getTenant(), epgId));
124             }
125         }
126
127         // Create tunnels on remote Nodes that may talk to us.
128         for (EgKey epg : epgs) {
129             Set<EgKey> peers = Sets.union(Collections.singleton(epg), policyInfo.getPeers(epg));
130             for (EgKey peer : peers) {
131                 for (NodeId remoteNodeId : ctx.getEndpointManager().getNodesForGroup(peer)) {
132
133                     // Please do not check for remote v local nodeID, we need local to local tunnels
134                     // in the case of chaining - The Great Dr Sunal.
135                     NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(remoteNodeId, TunnelTypeVxlan.class);
136                     if (tunPort == null) {
137                         LOG.trace("No tunnel port for tunnel in SourceMapper between local:{} and remote:{}",
138                                 nodeId.getValue(), remoteNodeId.getValue());
139                         continue;
140                     }
141                     flowMap.writeFlow(remoteNodeId, TABLE_ID, createTunnelFlow(tunPort, epFwdCtxOrds));
142                     flowMap.writeFlow(remoteNodeId, TABLE_ID, createBroadcastFlow(tunPort, epFwdCtxOrds));
143                 }
144             }
145         }
146     }
147
148     private Flow createBroadcastFlow(NodeConnectorId tunPort, EndpointFwdCtxOrdinals epFwdCtxOrds) {
149
150         int fdId = epFwdCtxOrds.getFdId();
151
152         MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
153         addNxTunIdMatch(mb, fdId);
154
155         // set condition group register to all ones to
156         // bypass
157         // policy enforcement
158         /*
159          * TODO: This breaks distributed policy enforcement
160          * especially wrt multi-action. BAD. Must be addressed
161          * (this is why we can't have nice things).
162          * This can be fixed with new tunnelId ordinal in
163          * Ordinal Factory.
164          */
165
166         Action fdReg = nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(fdId));
167
168         Match match = mb.build();
169         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "tunnelFdId", match);
170         FlowBuilder flowb = base().setId(flowid)
171             .setPriority(Integer.valueOf(150))
172             .setMatch(match)
173             .setInstructions(instructions(applyActionIns(fdReg), gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
174         return flowb.build();
175     }
176
177     private Flow createTunnelFlow(NodeConnectorId tunPort, EndpointFwdCtxOrdinals epFwdCtxOrds) {
178         // ... this is a remote node.
179
180         int egId = epFwdCtxOrds.getEpgId();
181         int bdId = epFwdCtxOrds.getBdId();
182         int fdId = epFwdCtxOrds.getFdId();
183         int l3Id = epFwdCtxOrds.getL3Id();
184         int tunnelId = epFwdCtxOrds.getTunnelId();
185
186         MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
187         addNxTunIdMatch(mb, tunnelId);
188
189         Action segReg = nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(egId));
190         // set condition group register to all ones to
191         // bypass
192         // policy enforcement
193         /*
194          * TODO: This breaks distributed policy enforcement
195          * especially wrt multi-action. BAD. Must be addressed
196          * (this is why we can't have nice things).
197          * This can be fixed with new tunnelId ordinal in
198          * Ordinal Factory.
199          */
200         Action scgReg = nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(0xffffff));
201         Action bdReg = nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(bdId));
202         Action fdReg = nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(fdId));
203         Action vrfReg = nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(l3Id));
204         Match match = mb.build();
205         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "tunnel", match);
206         FlowBuilder flowb = base().setId(flowid)
207             .setPriority(Integer.valueOf(150))
208             .setMatch(match)
209             .setInstructions(
210                     instructions(applyActionIns(segReg, scgReg, bdReg, fdReg, vrfReg),
211                             gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
212         return flowb.build();
213     }
214
215     private void syncEP(FlowMap flowMap, NodeId nodeId, Endpoint ep, NodeConnectorId ncId, EndpointFwdCtxOrdinals epFwdCtxOrds) throws Exception {
216
217         // TODO alagalah Li/Be: We should also match on EndpointL3 with the appropriate
218         // network containment. This would solve a lot of problems and prepare for EndpointL3 RPC.
219
220         int egId = epFwdCtxOrds.getEpgId();
221         int bdId = epFwdCtxOrds.getBdId();
222         int fdId = epFwdCtxOrds.getFdId();
223         int l3Id = epFwdCtxOrds.getL3Id();
224         int cgId = epFwdCtxOrds.getCgId();
225         int tunnelId = epFwdCtxOrds.getTunnelId();
226
227         Action segReg = nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(egId));
228         Action scgReg = nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(cgId));
229         Action bdReg = nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(bdId));
230         Action fdReg = nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(fdId));
231         Action vrfReg = nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(l3Id));
232         Action tunIdAction = nxLoadTunIdAction(BigInteger.valueOf(tunnelId), false);
233
234         Match match = new MatchBuilder().setEthernetMatch(ethernetMatch(ep.getMacAddress(), null, null))
235                 .setInPort(ncId)
236                 .build();
237         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "ep", match);
238         FlowBuilder flowb = base().setPriority(Integer.valueOf(100))
239             .setId(flowid)
240             .setMatch(match)
241             .setInstructions(
242                     instructions(applyActionIns(segReg, scgReg, bdReg, fdReg, vrfReg,tunIdAction),
243                             gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
244         flowMap.writeFlow(nodeId, TABLE_ID, flowb.build());
245     }
246
247 }