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.genius.infra.Datastore.Configuration;
18 import org.opendaylight.genius.infra.TypedWriteTransaction;
19 import org.opendaylight.genius.mdsalutil.NwConstants;
20 import org.opendaylight.netvirt.sfc.classifier.utils.AclMatches;
21 import org.opendaylight.netvirt.sfc.classifier.utils.OpenFlow13Utils;
22 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;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 public class OpenFlow13Provider {
39 // Unique cookie values for each type of flow
40 public static final BigInteger INGRESS_CLASSIFIER_FILTER_COOKIE = new BigInteger("F005BA1100000001", 16);
41 public static final BigInteger INGRESS_CLASSIFIER_ACL_COOKIE = new BigInteger("F005BA1100000002", 16);
42 public static final BigInteger EGRESS_CLASSIFIER_FILTER_COOKIE = new BigInteger("F005BA1100000003", 16);
43 public static final BigInteger EGRESS_CLASSIFIER_NEXTHOP_COOKIE = new BigInteger("F005BA1100000004", 16);
44 public static final BigInteger EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE = new BigInteger("F005BA1100000005", 16);
45 public static final BigInteger INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_COOKIE =
46 new BigInteger("F005BA1100000006", 16);
48 // Priorities for each flow
49 public static final int INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_PRIORITY = 10;
50 public static final int INGRESS_CLASSIFIER_FILTER_CHAIN_EGRESS_PRIORITY = 520;
51 public static final int INGRESS_CLASSIFIER_FILTER_NSH_TUN_PRIORITY = 510;
52 public static final int INGRESS_CLASSIFIER_FILTER_NSH_PRIORITY = 511;
53 public static final int INGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY = 500;
54 public static final int INGRESS_CLASSIFIER_ACL_MATCH_PRIORITY = 500;
55 public static final int INGRESS_CLASSIFIER_ACL_NOMATCH_PRIORITY = 10;
56 public static final int EGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY = 260;
57 public static final int EGRESS_CLASSIFIER_FILTER_NSH_PRIORITY = 250;
58 public static final int EGRESS_CLASSIFIER_NEXTHOP_PRIORITY = 250;
59 public static final int EGRESS_CLASSIFIER_EGRESS_PRIORITY = 250;
61 // Flow names for each table
62 public static final String INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_ETH_NSH_TRAFFIC_FLOW_NAME =
63 "nvsfc_ingr_class_capture_sfc_tunnel_eth_nsh";
64 public static final String INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_NSH_TRAFFIC_FLOW_NAME =
65 "nvsfc_ingr_class_capture_sfc_tunnel_nsh";
66 public static final String INGRESS_CLASSIFIER_FILTER_NSH_CHAIN_EGRESS_FLOW_NAME =
67 "nvsfc_ingr_class_filter_chain_egress";
68 public static final String INGRESS_CLASSIFIER_FILTER_NSH_TUN_FLOW_NAME = "nvsfc_ingr_class_filter_nsh_tun";
69 public static final String INGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME = "nvsfc_ingr_class_filter_nsh";
70 public static final String INGRESS_CLASSIFIER_FILTER_ETH_NSH_FLOW_NAME = "nvsfc_ingr_class_filter_eth_nsh";
71 public static final String INGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME = "nvsfc_ingr_class_filter_nonsh";
72 public static final String INGRESS_CLASSIFIER_ACL_FLOW_NAME = "nvsfc_ingr_class_acl";
73 public static final String EGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME = "nvsfc_egr_class_filter_nsh";
74 public static final String EGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME = "nvsfc_egr_class_filter_nonsh";
75 public static final String EGRESS_CLASSIFIER_NEXTHOP_FLOW_NAME = "nvsfc_egr_class_nexthop_noc1c2";
76 public static final String EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME = "nvsfc_egr_class_ tport egress";
78 public static final long SFC_TUNNEL_ID = 0L;
79 public static final String OF_URI_SEPARATOR = ":";
80 public static final Ipv4Address NULL_IP = new Ipv4Address("0.0.0.0");
82 public List<MatchBuilder> getMatchBuilderFromAceMatches(Matches matches) {
83 if (matches == null) {
87 return new AclMatches(matches).buildMatch();
90 public void appendFlowForCreate(NodeId node, Flow flow, TypedWriteTransaction<Configuration> tx) {
91 NodeKey nodeKey = new NodeKey(node);
92 InstanceIdentifier<Flow> iidFlow = InstanceIdentifier.builder(Nodes.class)
93 .child(Node.class, nodeKey)
94 .augmentation(FlowCapableNode.class)
95 .child(Table.class, new TableKey(flow.getTableId()))
96 .child(Flow.class, flow.key())
99 tx.put(iidFlow, flow, WriteTransaction.CREATE_MISSING_PARENTS);
102 public void appendFlowForDelete(NodeId node, Flow flow, TypedWriteTransaction<Configuration> tx) {
103 NodeKey nodeKey = new NodeKey(node);
104 InstanceIdentifier<Flow> iidFlow = InstanceIdentifier.builder(Nodes.class)
105 .child(Node.class, nodeKey)
106 .augmentation(FlowCapableNode.class)
107 .child(Table.class, new TableKey(flow.getTableId()))
108 .child(Flow.class, flow.key())
115 * Ingress Classifier SFC Tunnel Traffic Capture Flow
116 * Captures eth+nsh traffic coming from tunnel port, normalizes
117 * the packet type to nsh by removing the outer ethernet header
118 * and redirects it to the ingress classifier pipeline.
120 public Flow createIngressClassifierTunnelEthNshTrafficCaptureFlow(NodeId nodeId) {
121 MatchBuilder match = new MatchBuilder();
122 OpenFlow13Utils.addMatchTunId(match, SFC_TUNNEL_ID);
123 OpenFlow13Utils.addMatchEthNsh(match);
125 List<Action> actionList = new ArrayList<>();
126 actionList.add(OpenFlow13Utils.createActionNxDecap(actionList.size()));
128 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
129 OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE);
130 String flowIdStr = INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_ETH_NSH_TRAFFIC_FLOW_NAME + nodeId.getValue();
133 return OpenFlow13Utils.createFlowBuilder(NwConstants.INTERNAL_TUNNEL_TABLE,
134 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_PRIORITY,
135 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_COOKIE,
136 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_ETH_NSH_TRAFFIC_FLOW_NAME, flowIdStr, match, isb).build();
140 * Ingress Classifier SFC Tunnel Traffic Capture Flow
141 * Captures nsh traffic coming from tunnel port,
142 * and redirects it to the ingress classifier pipeline.
144 public Flow createIngressClassifierTunnelNshTrafficCaptureFlow(NodeId nodeId) {
145 MatchBuilder match = new MatchBuilder();
146 OpenFlow13Utils.addMatchTunId(match, SFC_TUNNEL_ID);
147 OpenFlow13Utils.addMatchPacketTypeNsh(match);
149 InstructionsBuilder isb = new InstructionsBuilder();
150 OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE);
151 String flowIdStr = INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_NSH_TRAFFIC_FLOW_NAME + nodeId.getValue();
154 return OpenFlow13Utils.createFlowBuilder(NwConstants.INTERNAL_TUNNEL_TABLE,
155 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_PRIORITY,
156 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_TRAFFIC_COOKIE,
157 INGRESS_CLASSIFIER_CAPTURE_SFC_TUNNEL_NSH_TRAFFIC_FLOW_NAME, flowIdStr, match, isb).build();
161 * Ingress Classifier Filter tunnel packet type NSH flow:
162 * Prevents nsh packets coming from a tunnel port to proceed.
163 * This is the least priority filter flow so it wont match
164 * packets coming from other than tunnel ports.
165 * Since no service port binding and thus no dispatching is
166 * available on tunnel port, resubmit direct to SFC pipeline.
168 public Flow createIngressClassifierFilterTunnelNshFlow(NodeId nodeId) {
169 MatchBuilder match = new MatchBuilder();
170 OpenFlow13Utils.addMatchPacketTypeNsh(match);
172 List<Action> actionList = new ArrayList<>();
173 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.SFC_TRANSPORT_INGRESS_TABLE,
176 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
177 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NSH_TUN_FLOW_NAME + nodeId.getValue();
179 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
180 INGRESS_CLASSIFIER_FILTER_NSH_TUN_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
181 INGRESS_CLASSIFIER_FILTER_NSH_TUN_FLOW_NAME, flowIdStr, match, isb).build();
185 * Ingress Classifier Filter Eth NSH flow:
186 * Prevents eth+nsh packets coming from other than a tunnel port
187 * to proceed. Verify that packet are not coming from tunnel
188 * by verifying there is no tunnel ip set with high priority
189 * flow. Resubmit to ingress dispatcher so that other nsh
190 * service handles the packet.
192 public Flow createIngressClassifierFilterEthNshFlow(NodeId nodeId) {
193 MatchBuilder match = new MatchBuilder();
194 OpenFlow13Utils.addMatchEthNsh(match);
195 OpenFlow13Utils.addMatchTunDstIp(match, NULL_IP);
197 List<Action> actionList = new ArrayList<>();
198 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
201 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
202 String flowIdStr = INGRESS_CLASSIFIER_FILTER_ETH_NSH_FLOW_NAME + nodeId.getValue();
204 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
205 INGRESS_CLASSIFIER_FILTER_NSH_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
206 INGRESS_CLASSIFIER_FILTER_ETH_NSH_FLOW_NAME, flowIdStr, match, isb).build();
210 * Ingress Classifier Filter packet type NSH floww:
211 * Prevents nsh packets coming from other than a tunnel port
212 * to proceed. Verify that packet are not coming from tunnel
213 * by checking there is no tunnel ip set with high priority
214 * flow. Resubmit to ingress dispatcher so that other nsh
215 * service handles the packet.
217 public Flow createIngressClassifierFilterNshFlow(NodeId nodeId) {
218 MatchBuilder match = new MatchBuilder();
219 OpenFlow13Utils.addMatchPacketTypeNsh(match);
220 OpenFlow13Utils.addMatchTunDstIp(match, NULL_IP);
222 List<Action> actionList = new ArrayList<>();
223 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
226 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
227 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME + nodeId.getValue();
229 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
230 INGRESS_CLASSIFIER_FILTER_NSH_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
231 INGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME, flowIdStr, match, isb).build();
235 * Classifier chain termination flow:
236 * Handle packets at the end of the chain for which the final
237 * destination might be the classifier node.
238 * Match nsh packets on classified paths at their final index.
239 * Restores the lport tag on reg6, removes the nsh header and
240 * resubmits to egress dispatcher.
242 public Flow createIngressClassifierFilterChainEgressFlow(NodeId nodeId, long nsp, short egressNsi) {
244 MatchBuilder match = new MatchBuilder();
245 OpenFlow13Utils.addMatchPacketTypeNsh(match);
246 OpenFlow13Utils.addMatchNsp(match, nsp);
247 OpenFlow13Utils.addMatchNsi(match, egressNsi);
249 List<Action> actionList = new ArrayList<>();
250 actionList.add(OpenFlow13Utils.createActionNxMoveNsc4ToReg6Register(actionList.size()));
251 actionList.add(OpenFlow13Utils.createActionNxDecap(actionList.size()));
252 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE,
255 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
256 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NSH_CHAIN_EGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
258 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
259 INGRESS_CLASSIFIER_FILTER_CHAIN_EGRESS_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
260 INGRESS_CLASSIFIER_FILTER_NSH_CHAIN_EGRESS_FLOW_NAME, flowIdStr, match, isb).build();
264 * Ingress Classifier Filter No NSH flow:
265 * Non nsh packets, those that have not been matched by other
266 * higher priority nsh matching flows, proceed to the ACL
269 public Flow createIngressClassifierFilterNoNshFlow(NodeId nodeId) {
271 MatchBuilder match = new MatchBuilder();
273 InstructionsBuilder isb = OpenFlow13Utils.appendGotoTableInstruction(new InstructionsBuilder(),
274 NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE);
275 String flowIdStr = INGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME + nodeId.getValue();
277 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_FILTER_TABLE,
278 INGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY, INGRESS_CLASSIFIER_FILTER_COOKIE,
279 INGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME, flowIdStr, match, isb).build();
283 * Ingress Classifier ACL flow:
284 * Performs the ACL classification, and sends packets to back
285 * to ingress dispatcher.
286 * Add the in_port (corresponds to Neutron NW/tenant) to the ACL match,
287 * and sets the nsp and nsi on the registry for later usage.
289 public Flow createIngressClassifierAclFlow(NodeId nodeId, MatchBuilder match, Long port, long nsp, short nsi) {
290 OpenFlow13Utils.addMatchInPort(match, nodeId, port);
292 List<Action> actionList = new ArrayList<>();
293 actionList.add(OpenFlow13Utils.createActionNxLoadNspToReg2High(nsp, actionList.size()));
294 actionList.add(OpenFlow13Utils.createActionNxLoadNsiToReg2Low(nsi, actionList.size()));
296 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
299 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
301 // The flowIdStr needs to be unique, so the best way to make it unique is to use the match
302 String flowIdStr = INGRESS_CLASSIFIER_ACL_FLOW_NAME + "_" + nodeId.getValue() + match.build().toString();
304 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE,
305 INGRESS_CLASSIFIER_ACL_MATCH_PRIORITY, INGRESS_CLASSIFIER_ACL_COOKIE, INGRESS_CLASSIFIER_ACL_FLOW_NAME,
306 flowIdStr, match, isb).build();
310 * Ingress Classifier ACL NoMatch flow:
311 * If there are no ACL classification matches, then resubmit back to
312 * the Ingress Dispatcher to let other services handle the packet.
314 public Flow createIngressClassifierAclNoMatchFlow(NodeId nodeId) {
315 // This is a MatchAny flow
316 MatchBuilder match = new MatchBuilder();
318 List<Action> actionList = new ArrayList<>();
319 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.LPORT_DISPATCHER_TABLE,
322 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
324 String flowIdStr = INGRESS_CLASSIFIER_ACL_FLOW_NAME + "_" + nodeId.getValue();
326 return OpenFlow13Utils.createFlowBuilder(NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE,
327 INGRESS_CLASSIFIER_ACL_NOMATCH_PRIORITY, INGRESS_CLASSIFIER_ACL_COOKIE,
328 INGRESS_CLASSIFIER_ACL_FLOW_NAME, flowIdStr, match, isb).build();
332 // Internal EgressFlow util methods
336 * Egress Classifier Filter NoNsh flow:
337 * Filters out packets that have not been classified in the
338 * ingress classifier, those for which registry has not
339 * been set with nsp and nsi. Resubmit to egress dispatcher.
341 public Flow createEgressClassifierFilterNoNshFlow(NodeId nodeId) {
342 MatchBuilder match = new MatchBuilder();
344 OpenFlow13Utils.addMatchReg2(match, 0);
346 List<Action> actionList = new ArrayList<>();
347 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE,
350 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
351 String flowIdStr = EGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME + nodeId.getValue();
353 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_FILTER_TABLE,
354 EGRESS_CLASSIFIER_FILTER_NONSH_PRIORITY, EGRESS_CLASSIFIER_FILTER_COOKIE,
355 EGRESS_CLASSIFIER_FILTER_NONSH_FLOW_NAME, flowIdStr, match, isb).build();
359 * Egress Classifier Filter Nsh flow.
360 * Packets proceed to NextHop table.
362 public Flow createEgressClassifierFilterNshFlow(NodeId nodeId) {
363 MatchBuilder match = new MatchBuilder();
365 InstructionsBuilder isb = new InstructionsBuilder();
366 isb = OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.EGRESS_SFC_CLASSIFIER_NEXTHOP_TABLE);
367 String flowIdStr = EGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME + nodeId.getValue();
369 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_FILTER_TABLE,
370 EGRESS_CLASSIFIER_FILTER_NSH_PRIORITY, EGRESS_CLASSIFIER_FILTER_COOKIE,
371 EGRESS_CLASSIFIER_FILTER_NSH_FLOW_NAME, flowIdStr, match, isb).build();
375 * Egress Classifier NextHop flow:
376 * Encapsulates the packet and sets the NSH header values.
377 * Packets proceed to TransportEgress table.
379 public Flow createEgressClassifierNextHopFlow(NodeId nodeId) {
380 final MatchBuilder match = new MatchBuilder();
382 List<Action> actionList = new ArrayList<>();
383 actionList.add(OpenFlow13Utils.createActionNxEncapNsh(actionList.size()));
384 actionList.add(OpenFlow13Utils.createActionNxMoveReg2HighToNsp(actionList.size()));
385 actionList.add(OpenFlow13Utils.createActionNxMoveReg2LowToNsi(actionList.size()));
386 actionList.add(OpenFlow13Utils.createActionNxLoadReg2(0, actionList.size()));
387 actionList.add(OpenFlow13Utils.createActionNxMoveReg0ToNsc1Register(actionList.size()));
388 actionList.add(OpenFlow13Utils.createActionNxMoveTunIdToNsc2Register(actionList.size()));
389 actionList.add(OpenFlow13Utils.createActionNxMoveReg6ToNsc4Register(actionList.size()));
390 actionList.add(OpenFlow13Utils.createActionNxLoadTunId(SFC_TUNNEL_ID, actionList.size()));
392 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
393 OpenFlow13Utils.appendGotoTableInstruction(isb, NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE);
394 String flowIdStr = EGRESS_CLASSIFIER_NEXTHOP_FLOW_NAME + nodeId.getValue();
396 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_NEXTHOP_TABLE,
397 EGRESS_CLASSIFIER_NEXTHOP_PRIORITY, EGRESS_CLASSIFIER_NEXTHOP_COOKIE,
398 EGRESS_CLASSIFIER_NEXTHOP_FLOW_NAME, flowIdStr, match, isb).build();
402 * Egress Classifier TransportEgress Local Flow
403 * First SFF is located on same node. NSH packets are
404 * sent to the SFC pipeline.
406 public Flow createEgressClassifierTransportEgressLocalFlow(NodeId nodeId, long nsp) {
407 MatchBuilder match = new MatchBuilder();
409 OpenFlow13Utils.addMatchPacketTypeNsh(match);
410 OpenFlow13Utils.addMatchNsp(match, nsp);
412 List<Action> actionList = new ArrayList<>();
413 actionList.add(OpenFlow13Utils.createActionResubmitTable(NwConstants.SFC_TRANSPORT_INGRESS_TABLE,
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_PRIORITY, EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE,
421 EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME, flowIdStr, match, isb).build();
425 * Egress Classifier TransportEgress Remote Flow
426 * Sends packet to a remote SFF ip though a tunnel port.
427 * Packets are not encapsulated with an extra ethernet header.
429 public Flow createEgressClassifierTransportEgressRemoteNshFlow(NodeId nodeId, long nsp, long outport,
431 MatchBuilder match = new MatchBuilder();
433 OpenFlow13Utils.addMatchPacketTypeNsh(match);
434 OpenFlow13Utils.addMatchNsp(match, nsp);
436 Long ipl = InetAddresses.coerceToInteger(InetAddresses.forString(firstHopIp)) & 0xffffffffL;
437 List<Action> actionList = new ArrayList<>();
438 actionList.add(OpenFlow13Utils.createActionNxLoadTunIpv4Dst(ipl, actionList.size()));
439 actionList.add(OpenFlow13Utils.createActionOutPort("output:" + outport, actionList.size()));
441 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
442 String flowIdStr = EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
444 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE,
445 EGRESS_CLASSIFIER_EGRESS_PRIORITY, EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE,
446 EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME, flowIdStr, match, isb).build();
450 * Egress Classifier TransportEgress Remote Flow
451 * Sends packet to a remote SFF ip though a tunnel port.
452 * Packets are encapsulated with an extra ethernet header.
454 public Flow createEgressClassifierTransportEgressRemoteEthNshFlow(NodeId nodeId, long nsp, long outport,
456 MatchBuilder match = new MatchBuilder();
458 OpenFlow13Utils.addMatchPacketTypeNsh(match);
459 OpenFlow13Utils.addMatchNsp(match, nsp);
461 Long ipl = InetAddresses.coerceToInteger(InetAddresses.forString(firstHopIp)) & 0xffffffffL;
462 List<Action> actionList = new ArrayList<>();
463 actionList.add(OpenFlow13Utils.createActionNxEncapEthernet(actionList.size()));
464 actionList.add(OpenFlow13Utils.createActionNxLoadTunIpv4Dst(ipl, actionList.size()));
465 actionList.add(OpenFlow13Utils.createActionOutPort("output:" + outport, actionList.size()));
467 InstructionsBuilder isb = OpenFlow13Utils.wrapActionsIntoApplyActionsInstruction(actionList);
468 String flowIdStr = EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME + nodeId.getValue() + "_" + nsp;
470 return OpenFlow13Utils.createFlowBuilder(NwConstants.EGRESS_SFC_CLASSIFIER_EGRESS_TABLE,
471 EGRESS_CLASSIFIER_EGRESS_PRIORITY, EGRESS_CLASSIFIER_TPORTEGRESS_COOKIE,
472 EGRESS_CLASSIFIER_TPORTEGRESS_FLOW_NAME, flowIdStr, match, isb).build();
477 public static Long getPortNoFromNodeConnector(String connector) {
479 * NodeConnectorId is of the form 'openflow:dpnid:portnum'
481 return Long.valueOf(connector.split(OF_URI_SEPARATOR)[2]);
484 public static BigInteger getDpnIdFromNodeId(NodeId nodeId) {
486 * NodeId is of the form 'openflow:dpnid'
488 return BigInteger.valueOf(Long.parseLong(nodeId.getValue().split(OF_URI_SEPARATOR)[1]));