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.annotation.Nullable;
16 import javax.inject.Singleton;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.genius.infra.Datastore.Configuration;
19 import org.opendaylight.genius.infra.TypedWriteTransaction;
20 import org.opendaylight.genius.mdsalutil.NwConstants;
21 import org.opendaylight.netvirt.sfc.classifier.utils.AclMatches;
22 import org.opendaylight.netvirt.sfc.classifier.utils.OpenFlow13Utils;
23 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;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
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.types.rev131026.flow.InstructionsBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 public class OpenFlow13Provider {
40 // Unique cookie values for each type of flow
41 public static final BigInteger INGRESS_CLASSIFIER_FILTER_COOKIE = new BigInteger("F005BA1100000001", 16);
42 public static final BigInteger INGRESS_CLASSIFIER_ACL_COOKIE = new BigInteger("F005BA1100000002", 16);
43 public static final BigInteger EGRESS_CLASSIFIER_FILTER_COOKIE = new BigInteger("F005BA1100000003", 16);
44 public static final BigInteger EGRESS_CLASSIFIER_NEXTHOP_COOKIE = new BigInteger("F005BA1100000004", 16);
45 public static final BigInteger EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE = new BigInteger("F005BA1100000005", 16);
46 public static final BigInteger INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_COOKIE =
47 new BigInteger("F005BA1100000006", 16);
49 // Priorities for each flow
50 public static final int INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_PRIORITY = 10;
51 public static final int INGRESS_CLASSIFIER_FILTER_CHAIN_EGRESS_PRIORITY = 520;
52 public static final int INGRESS_CLASSIFIER_FILTER_NSH_TUN_PRIORITY = 510;
53 public static final int INGRESS_CLASSIFIER_FILTER_NSH_PRIORITY = 511;
54 public static final int INGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY = 500;
55 public static final int INGRESS_CLASSIFIER_ACL_MATCH_PRIORITY = 500;
56 public static final int INGRESS_CLASSIFIER_ACL_NOMATCH_PRIORITY = 10;
57 public static final int EGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY = 260;
58 public static final int EGRESS_CLASSIFIER_FILTER_NSH_PRIORITY = 250;
59 public static final int EGRESS_CLASSIFIER_NEXTHOP_PRIORITY = 250;
60 public static final int EGRESS_CLASSIFIER_EGRESS_PRIORITY = 250;
62 // Flow names for each table
63 public static final String INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_ETH_NSH_TRAFFIC_FLOW_NAME =
64 "nvsfc_ingr_class_capture_sfc_tunnel_eth_nsh";
65 public static final String INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_NSH_TRAFFIC_FLOW_NAME =
66 "nvsfc_ingr_class_capture_sfc_tunnel_nsh";
67 public static final String INGRESS_CLASSIFIER_FILTER_NSH_CHAIN_EGRESS_FLOW_NAME =
68 "nvsfc_ingr_class_filter_chain_egress";
69 public static final String INGRESS_CLASSIFIER_FILTER_NSH_TUN_FLOW_NAME = "nvsfc_ingr_class_filter_nsh_tun";
70 public static final String INGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME = "nvsfc_ingr_class_filter_nsh";
71 public static final String INGRESS_CLASSIFIER_FILTER_ETH_NSH_FLOW_NAME = "nvsfc_ingr_class_filter_eth_nsh";
72 public static final String INGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME = "nvsfc_ingr_class_filter_nonsh";
73 public static final String INGRESS_CLASSIFIER_ACL_FLOW_NAME = "nvsfc_ingr_class_acl";
74 public static final String EGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME = "nvsfc_egr_class_filter_nsh";
75 public static final String EGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME = "nvsfc_egr_class_filter_nonsh";
76 public static final String EGRESS_CLASSIFIER_NEXTHOP_FLOW_NAME = "nvsfc_egr_class_nexthop_noc1c2";
77 public static final String EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME = "nvsfc_egr_class_ tport egress";
79 public static final long SFC_TUNNEL_ID = 0L;
80 public static final String OF_URI_SEPARATOR = ":";
81 public static final Ipv4Address NULL_IP = new Ipv4Address("0.0.0.0");
84 public List<MatchBuilder> getMatchBuilderFromAceMatches(Matches matches) {
85 if (matches == null) {
89 return new AclMatches(matches).buildMatch();
92 public void appendFlowForCreate(NodeId node, Flow flow, TypedWriteTransaction<Configuration> tx) {
93 NodeKey nodeKey = new NodeKey(node);
94 InstanceIdentifier<Flow> iidFlow = InstanceIdentifier.builder(Nodes.class)
95 .child(Node.class, nodeKey)
96 .augmentation(FlowCapableNode.class)
97 .child(Table.class, new TableKey(flow.getTableId()))
98 .child(Flow.class, flow.key())
101 tx.put(iidFlow, flow, WriteTransaction.CREATE_MISSING_PARENTS);
104 public void appendFlowForDelete(NodeId node, Flow flow, TypedWriteTransaction<Configuration> tx) {
105 NodeKey nodeKey = new NodeKey(node);
106 InstanceIdentifier<Flow> iidFlow = InstanceIdentifier.builder(Nodes.class)
107 .child(Node.class, nodeKey)
108 .augmentation(FlowCapableNode.class)
109 .child(Table.class, new TableKey(flow.getTableId()))
110 .child(Flow.class, flow.key())
117 * Ingress Classifier SFC Tunnel Traffic Capture Flow
118 * Captures eth+nsh traffic coming from tunnel port, normalizes
119 * the packet type to nsh by removing the outer ethernet header
120 * and redirects it to the ingress classifier pipeline.
122 public Flow createIngressClassifierTunnelEthNshTrafficCaptureFlow(NodeId nodeId) {
123 MatchBuilder match = new MatchBuilder();
124 OpenFlow13Utils.addMatchTunId(match, SFC_TUNNEL_ID);
125 OpenFlow13Utils.addMatchEthNsh(match);
127 List<Action> actionList = new ArrayList<>();
128 actionList.add(OpenFlow13Utils.createActionNxDecap(actionList.size()));
130 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
131 OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE);
132 String flowIdStr = INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_ETH_NSH_TRAFFIC_FLOW_NAME + nodeId.getValue();
135 return OpenFlow13Utils.createFlowBuilder(NwConstants.INTERNAL_TUNNEL_TABLE,
136 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_PRIORITY,
137 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_COOKIE,
138 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_ETH_NSH_TRAFFIC_FLOW_NAME, flowIdStr, match, isb).build();
142 * Ingress Classifier SFC Tunnel Traffic Capture Flow
143 * Captures nsh traffic coming from tunnel port,
144 * and redirects it to the ingress classifier pipeline.
146 public Flow createIngressClassifierTunnelNshTrafficCaptureFlow(NodeId nodeId) {
147 MatchBuilder match = new MatchBuilder();
148 OpenFlow13Utils.addMatchTunId(match, SFC_TUNNEL_ID);
149 OpenFlow13Utils.addMatchPacketTypeNsh(match);
151 InstructionsBuilder isb = new InstructionsBuilder();
152 OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE);
153 String flowIdStr = INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_NSH_TRAFFIC_FLOW_NAME + nodeId.getValue();
156 return OpenFlow13Utils.createFlowBuilder(NwConstants.INTERNAL_TUNNEL_TABLE,
157 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_PRIORITY,
158 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_COOKIE,
159 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_NSH_TRAFFIC_FLOW_NAME, flowIdStr, match, isb).build();
163 * Ingress Classifier Filter tunnel packet type NSH flow:
164 * Prevents nsh packets coming from a tunnel port to proceed.
165 * This is the least priority filter flow so it wont match
166 * packets coming from other than tunnel ports.
167 * Since no service port binding and thus no dispatching is
168 * available on tunnel port, resubmit direct to SFC pipeline.
170 public Flow createIngressClassifierFilterTunnelNshFlow(NodeId nodeId) {
171 MatchBuilder match = new MatchBuilder();
172 OpenFlow13Utils.addMatchPacketTypeNsh(match);
174 List<Action> actionList = new ArrayList<>();
175 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.SFC_TRANSPORT_INGRESS_TABLE,
178 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
179 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NSH_TUN_FLOW_NAME + nodeId.getValue();
181 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
182 INGRESS_CLASSIFIER_FILTER_NSH_TUN_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
183 INGRESS_CLASSIFIER_FILTER_NSH_TUN_FLOW_NAME, flowIdStr, match, isb).build();
187 * Ingress Classifier Filter Eth NSH flow:
188 * Prevents eth+nsh packets coming from other than a tunnel port
189 * to proceed. Verify that packet are not coming from tunnel
190 * by verifying there is no tunnel ip set with high priority
191 * flow. Resubmit to ingress dispatcher so that other nsh
192 * service handles the packet.
194 public Flow createIngressClassifierFilterEthNshFlow(NodeId nodeId) {
195 MatchBuilder match = new MatchBuilder();
196 OpenFlow13Utils.addMatchEthNsh(match);
197 OpenFlow13Utils.addMatchTunDstIp(match, NULL_IP);
199 List<Action> actionList = new ArrayList<>();
200 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
203 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
204 String flowIdStr = INGRESS_CLASSIFIER_FILTER_ETH_NSH_FLOW_NAME + nodeId.getValue();
206 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
207 INGRESS_CLASSIFIER_FILTER_NSH_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
208 INGRESS_CLASSIFIER_FILTER_ETH_NSH_FLOW_NAME, flowIdStr, match, isb).build();
212 * Ingress Classifier Filter packet type NSH floww:
213 * Prevents nsh packets coming from other than a tunnel port
214 * to proceed. Verify that packet are not coming from tunnel
215 * by checking there is no tunnel ip set with high priority
216 * flow. Resubmit to ingress dispatcher so that other nsh
217 * service handles the packet.
219 public Flow createIngressClassifierFilterNshFlow(NodeId nodeId) {
220 MatchBuilder match = new MatchBuilder();
221 OpenFlow13Utils.addMatchPacketTypeNsh(match);
222 OpenFlow13Utils.addMatchTunDstIp(match, NULL_IP);
224 List<Action> actionList = new ArrayList<>();
225 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
228 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
229 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME + nodeId.getValue();
231 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
232 INGRESS_CLASSIFIER_FILTER_NSH_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
233 INGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME, flowIdStr, match, isb).build();
237 * Classifier chain termination flow:
238 * Handle packets at the end of the chain for which the final
239 * destination might be the classifier node.
240 * Match nsh packets on classified paths at their final index.
241 * Restores the lport tag on reg6, removes the nsh header and
242 * resubmits to egress dispatcher.
244 public Flow createIngressClassifierFilterChainEgressFlow(NodeId nodeId, long nsp, short egressNsi) {
246 MatchBuilder match = new MatchBuilder();
247 OpenFlow13Utils.addMatchPacketTypeNsh(match);
248 OpenFlow13Utils.addMatchNsp(match, nsp);
249 OpenFlow13Utils.addMatchNsi(match, egressNsi);
251 List<Action> actionList = new ArrayList<>();
252 actionList.add(OpenFlow13Utils.createActionNxMoveNsc4ToReg6Register(actionList.size()));
253 actionList.add(OpenFlow13Utils.createActionNxDecap(actionList.size()));
254 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE,
257 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
258 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NSH_CHAIN_EGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
260 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
261 INGRESS_CLASSIFIER_FILTER_CHAIN_EGRESS_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
262 INGRESS_CLASSIFIER_FILTER_NSH_CHAIN_EGRESS_FLOW_NAME, flowIdStr, match, isb).build();
266 * Ingress Classifier Filter No NSH flow:
267 * Non nsh packets, those that have not been matched by other
268 * higher priority nsh matching flows, proceed to the ACL
271 public Flow createIngressClassifierFilterNoNshFlow(NodeId nodeId) {
273 MatchBuilder match = new MatchBuilder();
275 InstructionsBuilder isb = OpenFlow13Utils.appendGotoTableInstruction(new InstructionsBuilder(),
276 NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE);
277 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME + nodeId.getValue();
279 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
280 INGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
281 INGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME, flowIdStr, match, isb).build();
285 * Ingress Classifier ACL flow:
286 * Performs the ACL classification, and sends packets to back
287 * to ingress dispatcher.
288 * Add the in_port (corresponds to Neutron NW/tenant) to the ACL match,
289 * and sets the nsp and nsi on the registry for later usage.
291 public Flow createIngressClassifierAclFlow(NodeId nodeId, MatchBuilder match, Long port, long nsp, short nsi) {
292 OpenFlow13Utils.addMatchInPort(match, nodeId, port);
294 List<Action> actionList = new ArrayList<>();
295 actionList.add(OpenFlow13Utils.createActionNxLoadNspToReg2High(nsp, actionList.size()));
296 actionList.add(OpenFlow13Utils.createActionNxLoadNsiToReg2Low(nsi, actionList.size()));
298 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
301 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
303 // The flowIdStr needs to be unique, so the best way to make it unique is to use the match
304 String flowIdStr = INGRESS_CLASSIFIER_ACL_FLOW_NAME + "_" + nodeId.getValue() + match.build().toString();
306 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE,
307 INGRESS_CLASSIFIER_ACL_MATCH_PRIORITY, INGRESS_CLASSIFIER_ACL_COOKIE, INGRESS_CLASSIFIER_ACL_FLOW_NAME,
308 flowIdStr, match, isb).build();
312 * Ingress Classifier ACL NoMatch flow:
313 * If there are no ACL classification matches, then resubmit back to
314 * the Ingress Dispatcher to let other services handle the packet.
316 public Flow createIngressClassifierAclNoMatchFlow(NodeId nodeId) {
317 // This is a MatchAny flow
318 MatchBuilder match = new MatchBuilder();
320 List<Action> actionList = new ArrayList<>();
321 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
324 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
326 String flowIdStr = INGRESS_CLASSIFIER_ACL_FLOW_NAME + "_" + nodeId.getValue();
328 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE,
329 INGRESS_CLASSIFIER_ACL_NOMATCH_PRIORITY, INGRESS_CLASSIFIER_ACL_COOKIE,
330 INGRESS_CLASSIFIER_ACL_FLOW_NAME, flowIdStr, match, isb).build();
334 // Internal EgressFlow util methods
338 * Egress Classifier Filter NoNsh flow:
339 * Filters out packets that have not been classified in the
340 * ingress classifier, those for which registry has not
341 * been set with nsp and nsi. Resubmit to egress dispatcher.
343 public Flow createEgressClassifierFilterNoNshFlow(NodeId nodeId) {
344 MatchBuilder match = new MatchBuilder();
346 OpenFlow13Utils.addMatchReg2(match, 0);
348 List<Action> actionList = new ArrayList<>();
349 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE,
352 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
353 String flowIdStr = EGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME + nodeId.getValue();
355 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_FILTER_TABLE,
356 EGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY, EGRESS_CLASSIFIER_FILTER_COOKIE,
357 EGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME, flowIdStr, match, isb).build();
361 * Egress Classifier Filter Nsh flow.
362 * Packets proceed to NextHop table.
364 public Flow createEgressClassifierFilterNshFlow(NodeId nodeId) {
365 MatchBuilder match = new MatchBuilder();
367 InstructionsBuilder isb = new InstructionsBuilder();
368 isb = OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.EGRESS_SFC_CLASSIFIER_NEXTHOP_TABLE);
369 String flowIdStr = EGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME + nodeId.getValue();
371 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_FILTER_TABLE,
372 EGRESS_CLASSIFIER_FILTER_NSH_PRIORITY, EGRESS_CLASSIFIER_FILTER_COOKIE,
373 EGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME, flowIdStr, match, isb).build();
377 * Egress Classifier NextHop flow:
378 * Encapsulates the packet and sets the NSH header values.
379 * Packets proceed to TransportEgress table.
381 public Flow createEgressClassifierNextHopFlow(NodeId nodeId) {
382 final MatchBuilder match = new MatchBuilder();
384 List<Action> actionList = new ArrayList<>();
385 actionList.add(OpenFlow13Utils.createActionNxEncapNsh(actionList.size()));
386 actionList.add(OpenFlow13Utils.createActionNxMoveReg2HighToNsp(actionList.size()));
387 actionList.add(OpenFlow13Utils.createActionNxMoveReg2LowToNsi(actionList.size()));
388 actionList.add(OpenFlow13Utils.createActionNxLoadReg2(0, actionList.size()));
389 actionList.add(OpenFlow13Utils.createActionNxMoveReg0ToNsc1Register(actionList.size()));
390 actionList.add(OpenFlow13Utils.createActionNxMoveTunIdToNsc2Register(actionList.size()));
391 actionList.add(OpenFlow13Utils.createActionNxMoveReg6ToNsc4Register(actionList.size()));
392 actionList.add(OpenFlow13Utils.createActionNxLoadTunId(SFC_TUNNEL_ID, actionList.size()));
394 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
395 OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE);
396 String flowIdStr = EGRESS_CLASSIFIER_NEXTHOP_FLOW_NAME + nodeId.getValue();
398 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_NEXTHOP_TABLE,
399 EGRESS_CLASSIFIER_NEXTHOP_PRIORITY, EGRESS_CLASSIFIER_NEXTHOP_COOKIE,
400 EGRESS_CLASSIFIER_NEXTHOP_FLOW_NAME, flowIdStr, match, isb).build();
404 * Egress Classifier TransportEgress Local Flow
405 * First SFF is located on same node. NSH packets are
406 * sent to the SFC pipeline.
408 public Flow createEgressClassifierTransportEgressLocalFlow(NodeId nodeId, long nsp) {
409 MatchBuilder match = new MatchBuilder();
411 OpenFlow13Utils.addMatchPacketTypeNsh(match);
412 OpenFlow13Utils.addMatchNsp(match, nsp);
414 List<Action> actionList = new ArrayList<>();
415 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.SFC_TRANSPORT_INGRESS_TABLE,
418 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
419 String flowIdStr = EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
421 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE,
422 EGRESS_CLASSIFIER_EGRESS_PRIORITY, EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE,
423 EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME, flowIdStr, match, isb).build();
427 * Egress Classifier TransportEgress Remote Flow
428 * Sends packet to a remote SFF ip though a tunnel port.
429 * Packets are not encapsulated with an extra ethernet header.
431 public Flow createEgressClassifierTransportEgressRemoteNshFlow(NodeId nodeId, long nsp, long outport,
433 MatchBuilder match = new MatchBuilder();
435 OpenFlow13Utils.addMatchPacketTypeNsh(match);
436 OpenFlow13Utils.addMatchNsp(match, nsp);
438 Long ipl = InetAddresses.coerceToInteger(InetAddresses.forString(firstHopIp)) & 0xffffffffL;
439 List<Action> actionList = new ArrayList<>();
440 actionList.add(OpenFlow13Utils.createActionNxLoadTunIpv4Dst(ipl, actionList.size()));
441 actionList.add(OpenFlow13Utils.createActionOutPort("output:" + outport, actionList.size()));
443 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
444 String flowIdStr = EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
446 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE,
447 EGRESS_CLASSIFIER_EGRESS_PRIORITY, EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE,
448 EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME, flowIdStr, match, isb).build();
452 * Egress Classifier TransportEgress Remote Flow
453 * Sends packet to a remote SFF ip though a tunnel port.
454 * Packets are encapsulated with an extra ethernet header.
456 public Flow createEgressClassifierTransportEgressRemoteEthNshFlow(NodeId nodeId, long nsp, long outport,
458 MatchBuilder match = new MatchBuilder();
460 OpenFlow13Utils.addMatchPacketTypeNsh(match);
461 OpenFlow13Utils.addMatchNsp(match, nsp);
463 Long ipl = InetAddresses.coerceToInteger(InetAddresses.forString(firstHopIp)) & 0xffffffffL;
464 List<Action> actionList = new ArrayList<>();
465 actionList.add(OpenFlow13Utils.createActionNxEncapEthernet(actionList.size()));
466 actionList.add(OpenFlow13Utils.createActionNxLoadTunIpv4Dst(ipl, actionList.size()));
467 actionList.add(OpenFlow13Utils.createActionOutPort("output:" + outport, actionList.size()));
469 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
470 String flowIdStr = EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
472 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE,
473 EGRESS_CLASSIFIER_EGRESS_PRIORITY, EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE,
474 EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME, flowIdStr, match, isb).build();
479 public static Long getPortNoFromNodeConnector(String connector) {
481 * NodeConnectorId is of the form 'openflow:dpnid:portnum'
483 return Long.valueOf(connector.split(OF_URI_SEPARATOR)[2]);
486 public static BigInteger getDpnIdFromNodeId(NodeId nodeId) {
488 * NodeId is of the form 'openflow:dpnid'
490 return BigInteger.valueOf(Long.parseLong(nodeId.getValue().split(OF_URI_SEPARATOR)[1]));