51c6257ff76230a750698f5fbc8dcf146496d307
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / flow / IngressNatMapper.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
10
11 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.ARP;
12 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;
13 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.ethernetMatch;
14 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.gotoTableIns;
15 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;
16 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadArpOpAction;
17 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadArpShaAction;
18 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadArpSpaAction;
19 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadRegAction;
20 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIdAction;
21 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveArpShaToArpThaAction;
22 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveArpSpaToArpTpaAction;
23 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveEthSrcToEthDstAction;
24 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.outputAction;
25 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.setDlDstAction;
26 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.setDlSrcAction;
27 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.setIpv4DstAction;
28 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.setIpv6DstAction;
29
30 import java.math.BigInteger;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.Set;
34
35 import org.apache.commons.lang3.ArrayUtils;
36 import org.opendaylight.groupbasedpolicy.dto.EgKey;
37 import org.opendaylight.groupbasedpolicy.dto.EpKey;
38 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
39 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
40 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.Segmentation;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMove;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
74
75 import com.google.common.collect.Sets;
76
77 /**
78  * <h1>Manage the table processing NAT translation (table=1)</h1>
79  *
80  * Ingress NAT translation flows, created for every L3 endpoints with NAT which also contain L2 context
81  * <p>
82  * <i>Nat flow:</i><br>
83  * Priority = 100<br>
84  * Matches:<br>
85  *      - nw_dst (destination ip address)<br>
86  * Actions:<br>
87  *      - loadReg0 {@link NxmNxReg0}<br>
88  *      - loadReg1 {@link NxmNxReg1}<br>
89  *      - loadReg4 {@link NxmNxReg4}<br>
90  *      - loadReg5 {@link NxmNxReg5}<br>
91  *      - loadReg6 {@link NxmNxReg6}<br>
92  *      - loadTunnelId<br>
93  *      - {@link GoToTable} DESTINATION MAPPER table
94  * <p>
95  * <i>Outside Arp flow:</i><br>
96  * Priority = 150<br>
97  * Matches:<br>
98  *      - arp, (ethertype)<br>
99  *      - set arp target transport address<br>
100  * Actions:<br>
101  *      - move eth_src = eth_dst {@link NxRegMove}<br>
102  *      - set dl src_mac {@link MacAddress}<br>
103  *      - load arp_op {@link NxRegLoad}<br>
104  *      - move arp_sha = arp_tha {@link NxRegMove}<br>
105  *      - load arp_sha {@link NxRegLoad}<br>
106  *      - move arp_spa = arp_tpa {@link NxRegMove}<br>
107  *      - load arp_spa {@link NxRegLoad}<br>
108  *      - output:port {@link NodeConnectorId}
109  * <p>
110  * Flows for ingress traffic. Created for every external endpoint without location<br>
111  * <p>
112  * <i>Ingress external IP flow</i><br>
113  * Priority = 90<br>
114  * Matches:<br>
115  *      - nw_src (source ip address)<br>
116  * Actions:<br>
117  *      - loadReg0 {@link NxmNxReg0}<br>
118  *      - loadReg1 {@link NxmNxReg1}<br>
119  *      - loadReg4 {@link NxmNxReg4}<br>
120  *      - loadReg5 {@link NxmNxReg5}<br>
121  *      - loadReg6 {@link NxmNxReg6}<br>
122  *      - loadTunnelId<br>
123  *      - {@link GoToTable} DESTINATION MAPPER table
124  * <p>
125  * <i>Ingress external Arp flow</i><br>
126  * Priority = 80<br>
127  * Matches:<br>
128  *      - arp_spa (source arp address)<br>
129  * Actions:<br>
130  *      - loadReg0 {@link NxmNxReg0}<br>
131  *      - loadReg1 {@link NxmNxReg1}<br>
132  *      - loadReg4 {@link NxmNxReg4}<br>
133  *      - loadReg5 {@link NxmNxReg5}<br>
134  *      - loadReg6 {@link NxmNxReg6}<br>
135  *      - loadTunnelId<br>
136  *      - {@link GoToTable} DESTINATION MAPPER table
137  *
138  */
139 public class IngressNatMapper extends FlowTable {
140
141     protected static final Logger LOG = LoggerFactory.getLogger(IngressNatMapper.class);
142
143     // TODO Li alagalah Improve UT coverage for this class.
144     public static short TABLE_ID;
145
146     public IngressNatMapper(OfContext ctx, short tableId) {
147         super(ctx);
148         TABLE_ID = tableId;
149     }
150
151     @Override
152     public short getTableId() {
153         return TABLE_ID;
154     }
155
156     @Override
157     public void sync(NodeId nodeId, OfWriter ofWriter) throws Exception {
158
159         /*
160          * To support provider networks, all external ingress traffic is currently passed here and
161          * if no match is foud - no NAT is performed and processing continues in DestinationMapper.
162          */
163         Flow flow = base()
164                 .setTableId(TABLE_ID)
165                 .setPriority(1)
166             .setInstructions(
167                     FlowUtils.instructions(FlowUtils.gotoTableIns(
168                         ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())))
169                 .setId(FlowIdUtils.newFlowId("gotoDestinationMapper"))
170                 .build();
171         ofWriter.writeFlow(nodeId, TABLE_ID, flow);
172
173         // TODO Bug 3546 - Difficult: External port is unrelated to Tenant, L3C, L2BD..
174
175         // Flows for ingress NAT translation
176         Collection<Endpoint> endpointsForNode = ctx.getEndpointManager().getEndpointsForNode(nodeId);
177         Collection<EndpointL3> l3Endpoints = ctx.getEndpointManager().getL3EndpointsWithNat();
178         for (EndpointL3 l3Ep : l3Endpoints) {
179             if (l3Ep.getL2Context() != null && l3Ep.getMacAddress() !=null ) {
180                 Endpoint ep = ctx.getEndpointManager().getEndpoint(new EpKey(l3Ep.getL2Context(), l3Ep.getMacAddress()));
181                 if (endpointsForNode.contains(ep)) {
182                     createNatFlow(l3Ep, nodeId, ofWriter);
183                 }
184             }
185         }
186         //Flows for ingress traffic that does not have to be translated.
187         // TODO similar loop in DestinationMapper
188         for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
189             for (EgKey egKey : ctx.getEndpointManager().getEgKeysForEndpoint(ep)) {
190                 Set<EgKey> groups = ctx.getCurrentPolicy().getPeers(egKey);
191                 for (EgKey peer : Sets.union(Collections.singleton(egKey), ctx.getCurrentPolicy().getPeers(egKey))) {
192                     for (Endpoint extEp : ctx.getEndpointManager().getExtEpsNoLocForGroup(peer)) {
193                         createIngressExternalFlows(extEp, nodeId, ofWriter);
194                     }
195                 }
196             }
197         }
198     }
199
200     private void createNatFlow(EndpointL3 l3Ep, NodeId nodeId, OfWriter ofWriter) throws Exception {
201         NatAddress natAugL3Endpoint = l3Ep.getAugmentation(NatAddress.class);
202         // Match on L3 Nat Augmentation in Destination, set to IPAddress/Mac, send to SourceMapper
203         if (natAugL3Endpoint == null) {
204             return;
205         }
206         Endpoint ep = ctx.getEndpointManager().getEndpoint(new EpKey(l3Ep.getL2Context(), l3Ep.getMacAddress()));
207         EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, ep);
208         if (epFwdCtxOrds == null) {
209             LOG.info("getEndpointFwdCtxOrdinals is null for EP {}", ep);
210             return;
211         }
212         Flow flow = buildNatFlow(natAugL3Endpoint.getNatAddress(), l3Ep.getIpAddress(), l3Ep.getMacAddress(), epFwdCtxOrds);
213         if (flow != null) {
214             ofWriter.writeFlow(nodeId, TABLE_ID, flow);
215         }
216         flow = createOutsideArpFlow(l3Ep.getTenant(), natAugL3Endpoint.getNatAddress(), l3Ep.getMacAddress(), nodeId);
217         if (flow != null) {
218             ofWriter.writeFlow(nodeId, TABLE_ID, flow);
219         }
220     }
221
222     private void createIngressExternalFlows(Endpoint ep, NodeId nodeId, OfWriter ofWriter) throws Exception {
223         EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, ep);
224         if (epFwdCtxOrds == null) {
225             LOG.info("getEndpointFwdCtxOrdinals is null for EP {}", ep);
226             return;
227         }
228         if (ep.getL3Address() != null) {
229             for (L3Address l3Addr : ep.getL3Address()) {
230                 Flow ipFlow = buildIngressExternalIpFlow(l3Addr.getIpAddress(), epFwdCtxOrds);
231                 if (ipFlow != null) {
232                     ofWriter.writeFlow(nodeId, TABLE_ID, ipFlow);
233                 }
234             }
235         }
236         Flow arpFlow = buildIngressExternalArpFlow(ep.getMacAddress(), epFwdCtxOrds);
237         if (arpFlow != null) {
238             ofWriter.writeFlow(nodeId, TABLE_ID, arpFlow);
239         }
240     }
241
242     private Flow buildNatFlow(IpAddress outsideDestAddress, IpAddress insideDestAddress, MacAddress toMac,
243             EndpointFwdCtxOrdinals epFwdCtxOrds) {
244         Action setDestIp;
245         Action setDestMac = setDlDstAction(toMac);
246         FlowId flowid = new FlowId(new StringBuilder().append("IngressNat")
247             .append("|")
248             .append(outsideDestAddress)
249             .append("|")
250             .append(insideDestAddress)
251             .append("|")
252             .append(toMac)
253             .toString());
254         if (insideDestAddress.getIpv4Address() != null) {
255             setDestIp = setIpv4DstAction(insideDestAddress.getIpv4Address());
256         } else if (insideDestAddress.getIpv6Address() != null) {
257             setDestIp = setIpv6DstAction(insideDestAddress.getIpv6Address());
258         } else {
259             return null;
260         }
261         MatchBuilder mb = createMatchOnDstIpAddress(outsideDestAddress);
262         Action[] dstIpMacAction = {setDestIp, setDestMac};
263         FlowBuilder flowb = base().setPriority(100)
264             .setId(flowid)
265             .setMatch(mb.build())
266             .setInstructions(
267                     instructions(
268                             applyActionIns(ArrayUtils.addAll(dstIpMacAction, createEpFwdCtxActions(epFwdCtxOrds))),
269                             gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
270         return flowb.build();
271     }
272
273     private Flow createOutsideArpFlow(TenantId tenantId, IpAddress outsideDestAddress, MacAddress toMac, NodeId nodeId) {
274         String ikey = outsideDestAddress.getIpv4Address().getValue();
275         BigInteger intMac = new BigInteger(1, bytesFromHexString(toMac.getValue()));
276         MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, null, ARP)).setLayer3Match(
277                 new ArpMatchBuilder().setArpOp(1)
278                     .setArpTargetTransportAddress(new Ipv4Prefix(ikey + "/32"))
279                     .build());
280         Action[] outsideArpActions = {
281                 nxMoveEthSrcToEthDstAction(),
282                 setDlSrcAction(toMac),
283                 nxLoadArpOpAction(BigInteger.valueOf(2L)),
284                 nxMoveArpShaToArpThaAction(),
285                 nxLoadArpShaAction(intMac),
286                 nxMoveArpSpaToArpTpaAction(),
287                 nxLoadArpSpaAction(ikey),
288                 outputAction(new NodeConnectorId(nodeId.getValue() + ":INPORT"))
289         };
290         Subnet extSubnet = ExternalMapper.resolveSubnetForIpv4Address(ctx.getTenant(tenantId),
291                 outsideDestAddress.getIpv4Address());
292         L2FloodDomain l2Fd = null;
293         if (extSubnet != null && extSubnet.getParent() != null) {
294             l2Fd = ctx.getTenant(tenantId).resolveL2FloodDomain(extSubnet.getParent());
295         }
296         FlowBuilder flowb = base().setPriority(150);
297         if (l2Fd != null && l2Fd.getAugmentation(Segmentation.class) != null) {
298             Integer vlanId = l2Fd.getAugmentation(Segmentation.class).getSegmentationId();
299             mb.setVlanMatch(FlowUtils.vlanMatch(0, false));
300             Action[] pushVlanpActions = {FlowUtils.pushVlanAction(), FlowUtils.setVlanId(vlanId)};
301             flowb.setInstructions(instructions(FlowUtils.applyActionIns(ArrayUtils.addAll(
302                     pushVlanpActions,
303                     outsideArpActions))));
304         } else {
305             flowb.setInstructions(instructions(FlowUtils.applyActionIns(outsideArpActions)));
306         }
307         flowb.setId(FlowIdUtils.newFlowId(TABLE_ID, "outside-ip-arp", mb.build()));
308         flowb.setMatch(mb.build());
309         return flowb.build();
310     }
311
312     /**
313      * Builds flow for inbound IP traffic of registered external endpoint.
314      * Priority should be lower than in NAT flow.
315      */
316     private Flow buildIngressExternalIpFlow(IpAddress srcIpAddress, EndpointFwdCtxOrdinals epFwdCtxOrds) {
317         MatchBuilder mb = createMatchOnSrcIpAddress(srcIpAddress);
318         if (mb == null) {
319             return null;
320         }
321         FlowBuilder flowb = base().setPriority(90)
322             .setId(FlowIdUtils.newFlowId(TABLE_ID, "inbound-external-ip", mb.build()))
323             .setMatch(mb.build())
324             .setInstructions(
325                     instructions(applyActionIns(createEpFwdCtxActions(epFwdCtxOrds)),
326                             gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
327         return flowb.build();
328     }
329
330     /**
331      * @param srcIpAddress can be IPv4 or IPv6
332      * @return {@link MatchBuilder} with specified L2 ethertype and L3 source address.
333      *  Returns null if srcIpAddress is null.
334      */
335     private MatchBuilder createMatchOnSrcIpAddress(IpAddress srcIpAddress) {
336         return createMatchOnIpAddress(srcIpAddress, true);
337     }
338
339     private MatchBuilder createMatchOnDstIpAddress(IpAddress srcIpAddress) {
340         return createMatchOnIpAddress(srcIpAddress, false);
341     }
342
343     // use createMatchOnSrcIpAddress or createMatchOnDstIpAddress
344     private MatchBuilder createMatchOnIpAddress(IpAddress srcIpAddress, boolean isSourceAddress) {
345         MatchBuilder mb = new MatchBuilder();
346         String ipPrefix;
347         Layer3Match m;
348         if (srcIpAddress.getIpv4Address() != null) {
349             ipPrefix = srcIpAddress.getIpv4Address().getValue() + "/32";
350             m = (isSourceAddress) ? new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix(ipPrefix)).build() :
351                 new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ipPrefix)).build();
352             mb.setEthernetMatch(ethernetMatch(null, null, FlowUtils.IPv4))
353               .setLayer3Match(m);
354             return mb;
355         } else if (srcIpAddress.getIpv6Address() != null) {
356             ipPrefix = srcIpAddress.getIpv6Address().getValue() + "/128";
357             m = (isSourceAddress) ? new Ipv6MatchBuilder().setIpv6Source(new Ipv6Prefix(ipPrefix)).build() :
358                 new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ipPrefix)).build();
359             mb.setEthernetMatch(ethernetMatch(null, null, FlowUtils.IPv6))
360               .setLayer3Match(m);
361             return mb;
362         } else {
363             return null;
364         }
365     }
366
367     /**
368      * Builds flow for inbound ARP traffic of registered external endpoint.
369      * Priority should be lower than in ARP flow for NAT address.
370      */
371     private Flow buildIngressExternalArpFlow(MacAddress srcMac, EndpointFwdCtxOrdinals epFwdCtxOrds) {
372         if (srcMac == null) {
373             return null;
374         }
375         MatchBuilder mb = new MatchBuilder()
376             .setEthernetMatch(ethernetMatch(srcMac, null, ARP));
377             //.setLayer3Match(
378             //        new ArpMatchBuilder()
379            //             .setArpOp(Integer.valueOf(2))
380            //             .build());
381         FlowBuilder flowb = base().setPriority(80);
382         flowb.setInstructions(instructions(applyActionIns(createEpFwdCtxActions(epFwdCtxOrds)),
383                 gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
384         flowb.setId(FlowIdUtils.newFlowId(TABLE_ID, "inbound-external-arp", mb.build()));
385         flowb.setMatch(mb.build());
386         return flowb.build();
387     }
388
389     private Action[] createEpFwdCtxActions(EndpointFwdCtxOrdinals epFwdCtxOrds) {
390         int egId = epFwdCtxOrds.getEpgId();
391         int bdId = epFwdCtxOrds.getBdId();
392         int fdId = epFwdCtxOrds.getFdId();
393         int l3Id = epFwdCtxOrds.getL3Id();
394         int cgId = epFwdCtxOrds.getCgId();
395         int tunnelId = epFwdCtxOrds.getTunnelId();
396         Action segReg = nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(egId));
397         Action scgReg = nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(cgId));
398         Action bdReg = nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(bdId));
399         Action fdReg = nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(fdId));
400         Action vrfReg = nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(l3Id));
401         Action tunIdAction = nxLoadTunIdAction(BigInteger.valueOf(tunnelId), false);
402         return new Action[]{segReg, scgReg, bdReg, fdReg, vrfReg, tunIdAction};
403     }
404
405     static byte[] bytesFromHexString(String values) {
406         String target = "";
407         if (values != null) {
408             target = values;
409         }
410         String[] octets = target.split(":");
411
412         byte[] ret = new byte[octets.length];
413         for (int i = 0; i < octets.length; i++) {
414             ret[i] = Integer.valueOf(octets[i], 16).byteValue();
415         }
416         return ret;
417     }
418 }