Directions and flow creation for symmetric chain corrected
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / flow / ChainActionFlows.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.addNxNsiMatch;
12 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxNspMatch;
13 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxRegMatch;
14 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxTunIdMatch;
15 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxTunIpv4DstMatch;
16 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;
17 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.gotoTableIns;
18 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;
19 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadNshc1RegAction;
20 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadNshc2RegAction;
21 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadRegAction;
22 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIPv4Action;
23 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIdAction;
24 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxOutputRegAction;
25 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.outputAction;
26
27 import java.math.BigInteger;
28
29 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
30 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
31 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
32 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
33 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PolicyEnforcer.NetworkElements;
34 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ChainAction;
35 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils.SfcNshHeader;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlanGpe;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 public class ChainActionFlows {
55
56     private static final Logger LOG = LoggerFactory.getLogger(ChainAction.class);
57
58     public ChainActionFlows() {
59
60     }
61
62     public static void createChainTunnelFlows(SfcNshHeader sfcNshHeader, NetworkElements netElements, OfWriter ofWriter,
63             OfContext ctx) {
64
65         NodeId localNodeId = netElements.getLocalNodeId();
66         NodeId destNodeId = netElements.getDstEp().getAugmentation(OfOverlayContext.class).getNodeId();
67         EndpointFwdCtxOrdinals epOrdinals = netElements.getSrcEpOrdinals();
68
69         NodeConnectorId localNodeTunPort = ctx.getSwitchManager().getTunnelPort(localNodeId, TunnelTypeVxlanGpe.class);
70         NodeConnectorId destNodeTunPort = ctx.getSwitchManager().getTunnelPort(destNodeId, TunnelTypeVxlanGpe.class);
71         if (localNodeTunPort == null || destNodeTunPort == null) {
72             LOG.error("createChainTunnelFlows: No valid VXLAN GPE tunnel for Node {} or Node {}", localNodeId,
73                     destNodeId);
74             return;
75         }
76         ofWriter.writeFlow(localNodeId, ctx.getPolicyManager().getTABLEID_PORTSECURITY(),
77                 allowFromChainPort(localNodeTunPort, ctx.getPolicyManager().getTABLEID_PORTSECURITY(), ctx));
78
79         ofWriter.writeFlow(localNodeId, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER(),
80                 allowFromChainTunnel(localNodeTunPort, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()));
81
82         ofWriter.writeFlow(
83                 localNodeId,
84                 ctx.getPolicyManager().getTABLEID_EXTERNAL_MAPPER(),
85                 createExternalFlow(sfcNshHeader, localNodeTunPort, netElements, ctx.getPolicyManager()
86                     .getTABLEID_EXTERNAL_MAPPER(), ctx));
87
88         ofWriter.writeFlow(
89                 destNodeId,
90                 ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER(),
91                 createChainTunnelFlow(sfcNshHeader, destNodeTunPort, epOrdinals, ctx.getPolicyManager()
92                     .getTABLEID_SOURCE_MAPPER(), ctx));
93
94         ofWriter.writeFlow(
95                 destNodeId,
96                 ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER(),
97                 createChainBroadcastFlow(sfcNshHeader, destNodeTunPort, epOrdinals, ctx.getPolicyManager()
98                     .getTABLEID_SOURCE_MAPPER(), ctx));
99     }
100
101     private static Flow createChainBroadcastFlow(SfcNshHeader sfcNshHeader, NodeConnectorId tunPort,
102             EndpointFwdCtxOrdinals epFwdCtxOrds, short tableId, OfContext ctx) {
103
104         int fdId = epFwdCtxOrds.getFdId();
105
106         MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
107
108         addNxNsiMatch(mb, sfcNshHeader.getNshNsiFromChain());
109         addNxNspMatch(mb, sfcNshHeader.getNshNspFromChain());
110         addNxTunIdMatch(mb, fdId);
111
112         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action fdReg = nxLoadRegAction(
113                 NxmNxReg5.class, BigInteger.valueOf(fdId));
114
115         Match match = mb.build();
116         FlowId flowId = FlowIdUtils.newFlowId(tableId, "chainbroadcast", match);
117
118         FlowBuilder flowb = base(tableId).setId(flowId)
119             .setPriority(Integer.valueOf(150))
120             .setMatch(match)
121             .setInstructions(
122                     instructions(applyActionIns(fdReg), gotoTableIns(ctx.getPolicyManager()
123                         .getTABLEID_DESTINATION_MAPPER())));
124         return flowb.build();
125     }
126
127     private static Flow createExternalFlow(SfcNshHeader sfcNshHeader, NodeConnectorId tunPort,
128             NetworkElements netElements, short tableId, OfContext ctx) {
129
130         Integer priority = 1000;
131         int matchTunnelId=sfcNshHeader.getNshMetaC2().intValue();
132         Long l3c=Long.valueOf(netElements.getSrcEpOrdinals().getL3Id());
133
134         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadC1 = nxLoadNshc1RegAction(sfcNshHeader.getNshMetaC1());
135         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadC2 = nxLoadNshc2RegAction(sfcNshHeader.getNshMetaC2());
136         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunVnid = nxLoadTunIdAction(
137                 BigInteger.valueOf(sfcNshHeader.getNshMetaC2()), false);
138         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunDest = nxLoadTunIPv4Action(
139                 sfcNshHeader.getNshTunIpDst().getValue(), false);
140
141         MatchBuilder mb = new MatchBuilder();
142         addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, l3c));
143         addNxTunIdMatch(mb, matchTunnelId);
144         addNxNspMatch(mb, sfcNshHeader.getNshNspToChain());
145         addNxNsiMatch(mb, sfcNshHeader.getNshNsiToChain());
146         if (!netElements.getDstNodeId().equals(netElements.getSrcNodeId())) {
147             addNxTunIpv4DstMatch(mb, ctx.getSwitchManager()
148                 .getTunnelIP(netElements.getDstNodeId(), TunnelTypeVxlanGpe.class)
149                 .getIpv4Address());
150             priority = 1500;
151         }
152
153         Match match = mb.build();
154         FlowId flowId = FlowIdUtils.newFlowId(tableId, "chainexternal", match);
155         FlowBuilder flowb = base(tableId).setId(flowId)
156             .setPriority(Integer.valueOf(priority))
157             .setMatch(match)
158             .setInstructions(
159                     instructions(applyActionIns(loadC1, loadC2, loadChainTunDest, loadChainTunVnid,
160                             outputAction(tunPort))));
161         return flowb.build();
162     }
163
164     private static Flow createChainTunnelFlow(SfcNshHeader sfcNshHeader, NodeConnectorId tunPort,
165             EndpointFwdCtxOrdinals epFwdCtxOrds, short tableId, OfContext ctx) {
166
167         int egId = epFwdCtxOrds.getEpgId();
168         int bdId = epFwdCtxOrds.getBdId();
169         int fdId = epFwdCtxOrds.getFdId();
170         int l3Id = epFwdCtxOrds.getL3Id();
171         int tunnelId = epFwdCtxOrds.getTunnelId();
172
173         MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
174         addNxTunIdMatch(mb, tunnelId);
175         addNxNspMatch(mb, sfcNshHeader.getNshNspFromChain());
176         addNxNsiMatch(mb, sfcNshHeader.getNshNsiFromChain());
177
178         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action segReg = nxLoadRegAction(
179                 NxmNxReg0.class, BigInteger.valueOf(egId));
180         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action scgReg = nxLoadRegAction(
181                 NxmNxReg1.class, BigInteger.valueOf(0xffffff));
182         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action bdReg = nxLoadRegAction(
183                 NxmNxReg4.class, BigInteger.valueOf(bdId));
184         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action fdReg = nxLoadRegAction(
185                 NxmNxReg5.class, BigInteger.valueOf(fdId));
186         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action vrfReg = nxLoadRegAction(
187                 NxmNxReg6.class, BigInteger.valueOf(l3Id));
188
189         Match match = mb.build();
190         FlowId flowId = FlowIdUtils.newFlowId(tableId, "chaintunnel", match);
191         FlowBuilder flowb = base(tableId).setId(flowId)
192             .setPriority(Integer.valueOf(150))
193             .setMatch(match)
194             .setInstructions(
195                     instructions(applyActionIns(segReg, scgReg, bdReg, fdReg, vrfReg),
196                             gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
197         return flowb.build();
198     }
199
200     private static Flow allowFromChainPort(NodeConnectorId port, short tableId, OfContext ctx) {
201
202         Match match = new MatchBuilder().setInPort(port).build();
203         FlowId flowId = FlowIdUtils.newFlowId(tableId, "chainport", match);
204         FlowBuilder flowb = base(tableId).setId(flowId)
205             .setPriority(Integer.valueOf(200))
206             .setMatch(match)
207             .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()));
208         return flowb.build();
209     }
210
211     private static Flow allowFromChainTunnel(NodeConnectorId tunPort, short tableId) {
212
213         MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
214         addNxRegMatch(mb, RegMatch.of(NxmNxReg1.class, Long.valueOf(0xffffff)));
215         Match match = mb.build();
216         FlowId flowId = FlowIdUtils.newFlowId(tableId, "chainport", match);
217
218         FlowBuilder flow = base(tableId).setId(flowId)
219             .setMatch(match)
220             .setPriority(65000)
221             .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
222         return flow.build();
223
224     }
225
226     /**
227      * Get a base flow builder with some common features already set
228      */
229     private static FlowBuilder base(short tableId) {
230         return new FlowBuilder().setTableId(tableId).setBarrier(false).setHardTimeout(0).setIdleTimeout(0);
231     }
232 }