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