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