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