2 * Copyright © 2017 Ericsson, Inc. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.sfc.classifier.providers;
11 import com.google.common.net.InetAddresses;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import javax.inject.Singleton;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.genius.mdsalutil.NwConstants;
19 import org.opendaylight.netvirt.sfc.classifier.utils.AclMatches;
20 import org.opendaylight.netvirt.sfc.classifier.utils.OpenFlow13Utils;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 public class OpenFlow13Provider {
38 // Unique cookie values for each type of flow
39 public static final BigInteger INGRESS_CLASSIFIER_FILTER_COOKIE = new BigInteger("F005BA1100000001", 16);
40 public static final BigInteger INGRESS_CLASSIFIER_ACL_COOKIE = new BigInteger("F005BA1100000002", 16);
41 public static final BigInteger EGRESS_CLASSIFIER_FILTER_COOKIE = new BigInteger("F005BA1100000003", 16);
42 public static final BigInteger EGRESS_CLASSIFIER_NEXTHOP_COOKIE = new BigInteger("F005BA1100000004", 16);
43 public static final BigInteger EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE = new BigInteger("F005BA1100000005", 16);
44 public static final BigInteger INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_COOKIE =
45 new BigInteger("F005BA1100000006", 16);
47 // Priorities for each flow
48 public static final int INGRESS_CLASSIFIER_FILTER_CHAIN_EGRESS_PRIORITY = 520;
49 public static final int INGRESS_CLASSIFIER_FILTER_TUN_NSH_PRIORITY = 510;
50 public static final int INGRESS_CLASSIFIER_FILTER_ETH_NSH_PRIORITY = 511;
51 public static final int INGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY = 500;
52 public static final int INGRESS_CLASSIFIER_ACL_PRIORITY = 500;
53 public static final int INGRESS_CLASSIFIER_ACL_NOMATCH_PRIORITY = 10;
54 public static final int INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_PRIORITY = 10;
55 public static final int EGRESS_CLASSIFIER_FILTER_NSH_PRIORITY = 260;
56 public static final int EGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY = 250;
57 public static final int EGRESS_CLASSIFIER_NEXTHOP_C1C2_PRIORITY = 250;
58 public static final int EGRESS_CLASSIFIER_NEXTHOP_NOC1C2_PRIORITY = 260;
59 public static final int EGRESS_CLASSIFIER_EGRESS_LOCAL_PRIORITY = 260;
60 public static final int EGRESS_CLASSIFIER_EGRESS_REMOTE_PRIORITY = 250;
62 // Flow names for each table
63 public static final String INGRESS_CLASSIFIER_FILTER_NSH_CHAIN_EGRESS_FLOW_NAME =
64 "nvsfc_ingr_class_filter_chain_egress";
65 public static final String INGRESS_CLASSIFIER_FILTER_VXGPENSH_FLOW_NAME = "nvsfc_ingr_class_filter_vxgpe";
66 public static final String INGRESS_CLASSIFIER_FILTER_ETHNSH_FLOW_NAME = "nvsfc_ingr_class_filter_eth";
67 public static final String INGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME = "nvsfc_ingr_class_filter_nonsh";
68 public static final String INGRESS_CLASSIFIER_ACL_FLOW_NAME = "nvsfc_ingr_class_acl";
69 public static final String INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_FLOW_NAME =
70 "nvsfc_ingr_class_capture_sfc_tunnel";
71 public static final String EGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME = "nvsfc_egr_class_filter_nsh";
72 public static final String EGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME = "nvsfc_egr_class_filter_nonsh";
73 public static final String EGRESS_CLASSIFIER_NEXTHOP_C1C2_FLOW_NAME = "nvsfc_egr_class_nexthop_c1c2";
74 public static final String EGRESS_CLASSIFIER_NEXTHOP_NOC1C2_FLOW_NAME = "nvsfc_egr_class_nexthop_noc1c2";
75 public static final String EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME = "nvsfc_egr_class_ tport egress";
77 public static final short NSH_MDTYPE_ONE = 0x01;
78 public static final short NSH_NP_ETH = 0x3;
79 public static final long DEFAULT_NSH_CONTEXT_VALUE = 0L;
80 public static final long ACL_FLAG_CONTEXT_VALUE = 0xFFFFFFL;
81 public static final long SFC_TUNNEL_ID = 0L;
82 public static final String OF_URI_SEPARATOR = ":";
83 public static final Ipv4Address NULL_IP = new Ipv4Address("0.0.0.0");
85 public MatchBuilder getMatchBuilderFromAceMatches(Matches matches) {
86 if (matches == null) {
90 return new AclMatches(matches).buildMatch();
93 public void appendFlowForCreate(NodeId node, Flow flow, WriteTransaction tx) {
94 NodeKey nodeKey = new NodeKey(node);
95 InstanceIdentifier<Flow> iidFlow = InstanceIdentifier.builder(Nodes.class)
96 .child(Node.class, nodeKey)
97 .augmentation(FlowCapableNode.class)
98 .child(Table.class, new TableKey(flow.getTableId()))
99 .child(Flow.class, flow.getKey())
102 tx.put(LogicalDatastoreType.CONFIGURATION, iidFlow, flow, WriteTransaction.CREATE_MISSING_PARENTS);
105 public void appendFlowForDelete(NodeId node, Flow flow, WriteTransaction tx) {
106 NodeKey nodeKey = new NodeKey(node);
107 InstanceIdentifier<Flow> iidFlow = InstanceIdentifier.builder(Nodes.class)
108 .child(Node.class, nodeKey)
109 .augmentation(FlowCapableNode.class)
110 .child(Table.class, new TableKey(flow.getTableId()))
111 .child(Flow.class, flow.getKey())
114 tx.delete(LogicalDatastoreType.CONFIGURATION, iidFlow);
118 * Ingress Classifier SFC Tunnel Traffic Capture Flow
119 * Captures SFC traffic coming from tunnel port and redirects it
120 * to the ingress classifier pipeline. From there, if no chain
121 * egress actions apply, it will be sent back to SFC pipeline.
122 * Match on SFC VNI = 0 and ethertype = nsh, and resubmit to
123 * ingress classifier.
125 public Flow createIngressClassifierSfcTunnelTrafficCaptureFlow(NodeId nodeId) {
126 MatchBuilder match = new MatchBuilder();
127 OpenFlow13Utils.addMatchTunId(match, SFC_TUNNEL_ID);
128 OpenFlow13Utils.addMatchEthNsh(match);
130 List<Action> actionList = new ArrayList<>();
131 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
134 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
135 String flowIdStr = INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_FLOW_NAME + nodeId.getValue();
138 return OpenFlow13Utils.createFlowBuilder(NwConstants.INTERNAL_TUNNEL_TABLE,
139 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_PRIORITY,
140 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_COOKIE,
141 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_FLOW_NAME, flowIdStr, match, isb).build();
145 * Ingress Classifier Filter Vxgpe NSH flow:
146 * Only allows Non-NSH packets to proceed in the classifier
147 * Match on ethertype and resubmit to SFC (we don't resubmit to
148 * dispatcher since it is still not used for tunnel ports)
150 public Flow createIngressClassifierFilterVxgpeNshFlow(NodeId nodeId) {
151 MatchBuilder match = new MatchBuilder();
152 OpenFlow13Utils.addMatchEthNsh(match);
154 List<Action> actionList = new ArrayList<>();
155 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.SFC_TRANSPORT_INGRESS_TABLE,
158 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
159 String flowIdStr = INGRESS_CLASSIFIER_FILTER_VXGPENSH_FLOW_NAME + nodeId.getValue();
161 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
162 INGRESS_CLASSIFIER_FILTER_TUN_NSH_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
163 INGRESS_CLASSIFIER_FILTER_VXGPENSH_FLOW_NAME, flowIdStr, match, isb).build();
167 * Ingress Classifier Filter Eth NSH flow:
168 * Only allows Non-NSH packets to proceed in the classifier
169 * Match on ethertype and null tunnel IP and resubmit to
170 * Ingress Dispatcher on match
172 public Flow createIngressClassifierFilterEthNshFlow(NodeId nodeId) {
173 MatchBuilder match = new MatchBuilder();
174 OpenFlow13Utils.addMatchEthNsh(match);
175 OpenFlow13Utils.addMatchTunDstIp(match, NULL_IP);
177 List<Action> actionList = new ArrayList<>();
178 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
181 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
182 String flowIdStr = INGRESS_CLASSIFIER_FILTER_ETHNSH_FLOW_NAME + nodeId.getValue();
184 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
185 INGRESS_CLASSIFIER_FILTER_ETH_NSH_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
186 INGRESS_CLASSIFIER_FILTER_ETHNSH_FLOW_NAME, flowIdStr, match, isb).build();
190 * Classifier chain termination flow:
191 * Handle packets at the end of the chain
192 * Match C1 on local IP, NSP and ending NSI, restore metadata and
193 * resubmit to egress dispatcher
195 public Flow createIngressClassifierFilterChainEgressFlow(NodeId nodeId, long nsp, short egressNsi) {
197 MatchBuilder match = new MatchBuilder();
198 OpenFlow13Utils.addMatchNsp(match, nsp);
199 OpenFlow13Utils.addMatchNsi(match, egressNsi);
201 List<Action> actionList = new ArrayList<>();
202 actionList.add(OpenFlow13Utils.createActionNxMoveNsc4ToReg6Register(actionList.size()));
203 actionList.add(OpenFlow13Utils.createActionNxPopNsh(actionList.size()));
204 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE,
207 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
208 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NSH_CHAIN_EGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
210 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
211 INGRESS_CLASSIFIER_FILTER_CHAIN_EGRESS_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
212 INGRESS_CLASSIFIER_FILTER_NSH_CHAIN_EGRESS_FLOW_NAME, flowIdStr, match, isb).build();
216 * Ingress Classifier Filter No NSH flow:
217 * Only allows Non-NSH packets to proceed in the classifier
218 * Match Any (NSH not present), Goto Classifier ACL table
220 public Flow createIngressClassifierFilterNoNshFlow(NodeId nodeId) {
222 MatchBuilder match = new MatchBuilder();
224 InstructionsBuilder isb = OpenFlow13Utils.appendGotoTableInstruction(new InstructionsBuilder(),
225 NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE);
226 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME + nodeId.getValue();
228 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
229 INGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
230 INGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME, flowIdStr, match, isb).build();
234 * Ingress Classifier ACL flow:
235 * Performs the ACL classification, and sends packets to Ingress Dispatcher
236 * Match on inport (corresponds to Neutron NW/tenant), Push NSH, init(nsp, nsi, C1, C2),
237 * and resubmit to Ingress Dispatcher to be sent down the rest of
240 public Flow createIngressClassifierAclFlow(NodeId nodeId, MatchBuilder match, Long port, long nsp, short nsi) {
241 OpenFlow13Utils.addMatchInPort(match, nodeId, port);
243 List<Action> actionList = new ArrayList<>();
244 actionList.add(OpenFlow13Utils.createActionNxPushNsh(actionList.size()));
245 actionList.add(OpenFlow13Utils.createActionNxLoadNshMdtype(NSH_MDTYPE_ONE, actionList.size()));
246 actionList.add(OpenFlow13Utils.createActionNxLoadNp(NSH_NP_ETH, actionList.size()));
247 actionList.add(OpenFlow13Utils.createActionNxLoadNsp((int) nsp, actionList.size()));
248 actionList.add(OpenFlow13Utils.createActionNxLoadNsi(nsi, actionList.size()));
249 actionList.add(OpenFlow13Utils.createActionNxLoadNshc1(ACL_FLAG_CONTEXT_VALUE, actionList.size()));
250 actionList.add(OpenFlow13Utils.createActionNxLoadNshc2(DEFAULT_NSH_CONTEXT_VALUE, actionList.size()));
251 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
254 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
256 // The flowIdStr needs to be unique, so the best way to make it unique is to use the match
257 String flowIdStr = INGRESS_CLASSIFIER_ACL_FLOW_NAME + "_" + nodeId.getValue() + match.build().toString();
259 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE,
260 INGRESS_CLASSIFIER_ACL_PRIORITY, INGRESS_CLASSIFIER_ACL_COOKIE, INGRESS_CLASSIFIER_ACL_FLOW_NAME,
261 flowIdStr, match, isb).build();
265 * Ingress Classifier ACL NoMatch flow:
266 * If there are no ACL classification matches, then resubmit back to
267 * the Ingress Dispatcher to let other services handle the packet.
269 public Flow createIngressClassifierAclNoMatchFlow(NodeId nodeId) {
270 // This is a MatchAny flow
271 MatchBuilder match = new MatchBuilder();
273 List<Action> actionList = new ArrayList<>();
274 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
277 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
279 String flowIdStr = INGRESS_CLASSIFIER_ACL_FLOW_NAME + "_" + nodeId.getValue();
281 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE,
282 INGRESS_CLASSIFIER_ACL_NOMATCH_PRIORITY, INGRESS_CLASSIFIER_ACL_COOKIE,
283 INGRESS_CLASSIFIER_ACL_FLOW_NAME, flowIdStr, match, isb).build();
287 // Internal EgressFlow util methods
291 * Egress Classifier Filter NSH flow:
292 * Only allows NSH packets to proceed in the egress classifier
293 * Match on NSH MdType=1, Goto table Egress Classifier NextHop on match
294 * Since we need to check if the packet has passed through the classifier and has been
295 * encapsulated with NSH. We cant check for Vxgpe+NSH or Eth+NSH yet, since the outer
296 * encapsulation wont be added until the packet egresses, so instead check for NSH MD-type,
297 * which was set in the classification flow.
299 public Flow createEgressClassifierFilterNshFlow(NodeId nodeId) {
300 MatchBuilder match = new MatchBuilder();
301 OpenFlow13Utils.addMatchNshNsc1(match, ACL_FLAG_CONTEXT_VALUE);
303 List<Action> actionList = new ArrayList<>();
304 actionList.add(OpenFlow13Utils.createActionNxLoadNshc1(DEFAULT_NSH_CONTEXT_VALUE, actionList.size()));
306 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
307 isb = OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.EGRESS_SFC_CLASSIFIER_NEXTHOP_TABLE);
308 String flowIdStr = EGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME + nodeId.getValue();
310 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_FILTER_TABLE,
311 EGRESS_CLASSIFIER_FILTER_NSH_PRIORITY, EGRESS_CLASSIFIER_FILTER_COOKIE,
312 EGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME, flowIdStr, match, isb).build();
316 * Egress Classifier Filter No NSH flow:
317 * Only allows NSH packets to proceed in the egress classifier
318 * MatchAny (NSH not present), Resubmit to Egress Dispatcher
319 * since the packet is not for SFC
321 public Flow createEgressClassifierFilterNoNshFlow(NodeId nodeId) {
322 MatchBuilder match = new MatchBuilder();
324 List<Action> actionList = new ArrayList<>();
325 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE,
328 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
329 String flowIdStr = EGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME + nodeId.getValue();
331 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_FILTER_TABLE,
332 EGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY, EGRESS_CLASSIFIER_FILTER_COOKIE,
333 EGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME, flowIdStr, match, isb).build();
337 * Egress Classifier NextHop No C1/C2 flow:
338 * Set C1/C2 accordingly
339 * Match [C1, C2] == [0, 0], Move [TunIpv4Dst, TunVnid] to [C1, C2],
340 * Move Reg0 (SFF IP) to TunIpv4Dst, and goto Egress Classifier
341 * Transport Egress table on match
343 public Flow createEgressClassifierNextHopNoC1C2Flow(NodeId nodeId) {
344 MatchBuilder match = new MatchBuilder();
345 OpenFlow13Utils.addMatchNshNsc1(match, DEFAULT_NSH_CONTEXT_VALUE);
346 OpenFlow13Utils.addMatchNshNsc2(match, DEFAULT_NSH_CONTEXT_VALUE);
348 List<Action> actionList = new ArrayList<>();
349 actionList.add(OpenFlow13Utils.createActionNxMoveReg0ToNsc1Register(actionList.size()));
350 actionList.add(OpenFlow13Utils.createActionNxMoveTunIdToNsc2Register(actionList.size()));
351 actionList.add(OpenFlow13Utils.createActionNxMoveReg6ToNsc4Register(actionList.size()));
352 actionList.add(OpenFlow13Utils.createActionNxLoadTunId(SFC_TUNNEL_ID, actionList.size()));
354 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
355 OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE);
356 String flowIdStr = EGRESS_CLASSIFIER_NEXTHOP_NOC1C2_FLOW_NAME + nodeId.getValue();
358 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_NEXTHOP_TABLE,
359 EGRESS_CLASSIFIER_NEXTHOP_NOC1C2_PRIORITY, EGRESS_CLASSIFIER_NEXTHOP_COOKIE,
360 EGRESS_CLASSIFIER_NEXTHOP_NOC1C2_FLOW_NAME, flowIdStr, match, isb).build();
364 * Egress Classifier NextHop with C1/C2 flow:
365 * Set C1/C2 accordingly
366 * MatchAny (C1, C2 already set) goto Egress Classifier
367 * Transport Egress table
369 public Flow createEgressClassifierNextHopC1C2Flow(NodeId nodeId) {
370 MatchBuilder match = new MatchBuilder();
372 InstructionsBuilder isb = OpenFlow13Utils.appendGotoTableInstruction(new InstructionsBuilder(),
373 NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE);
374 String flowIdStr = EGRESS_CLASSIFIER_NEXTHOP_C1C2_FLOW_NAME + nodeId.getValue();
376 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_NEXTHOP_TABLE,
377 EGRESS_CLASSIFIER_NEXTHOP_C1C2_PRIORITY, EGRESS_CLASSIFIER_NEXTHOP_COOKIE,
378 EGRESS_CLASSIFIER_NEXTHOP_C1C2_FLOW_NAME, flowIdStr, match, isb).build();
382 * Egress Classifier TransportEgress Local Flow
383 * Final egress processing and egress packets. Resubmit to Ingress
384 * Dispatcher to be processed by SFC SFF on match
386 public Flow createEgressClassifierTransportEgressLocalFlow(NodeId nodeId, long nsp) {
387 MatchBuilder match = OpenFlow13Utils.getNspMatch(nsp);
389 List<Action> actionList = new ArrayList<>();
390 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.SFC_TRANSPORT_INGRESS_TABLE,
393 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
394 String flowIdStr = EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
396 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE,
397 EGRESS_CLASSIFIER_EGRESS_LOCAL_PRIORITY, EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE,
398 EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME, flowIdStr, match, isb).build();
402 * Egress Classifier TransportEgress Remote Flow
403 * Final egress processing and egress packets. Determines if the
404 * packet should go to a local or remote SFF.
405 * Match on Nsp, Output to port to send to remote SFF on match.
407 public Flow createEgressClassifierTransportEgressRemoteFlow(NodeId nodeId, long nsp, long outport,
409 MatchBuilder match = OpenFlow13Utils.getNspMatch(nsp);
411 Long ipl = InetAddresses.coerceToInteger(InetAddresses.forString(firstHopIp)) & 0xffffffffL;
412 List<Action> actionList = new ArrayList<>();
413 actionList.add(OpenFlow13Utils.createActionNxLoadTunIpv4Dst(ipl, actionList.size()));
414 actionList.add(OpenFlow13Utils.createActionOutPort("output:" + outport, actionList.size()));
416 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
417 String flowIdStr = EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
419 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE,
420 EGRESS_CLASSIFIER_EGRESS_REMOTE_PRIORITY, EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE,
421 EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME, flowIdStr, match, isb).build();
424 public static Long getPortNoFromNodeConnector(String connector) {
426 * NodeConnectorId is of the form 'openflow:dpnid:portnum'
428 return Long.valueOf(connector.split(OF_URI_SEPARATOR)[2]);
431 public static BigInteger getDpnIdFromNodeId(NodeId nodeId) {
433 * NodeId is of the form 'openflow:dpnid'
435 return BigInteger.valueOf(Long.parseLong(nodeId.getValue().split(OF_URI_SEPARATOR)[1]));