Merge "Bug #1752 swap egress/ingress ACLs"
[ovsdb.git] / utils / mdsal-openflow / src / main / java / org / opendaylight / ovsdb / utils / mdsal / openflow / ActionUtils.java
1 /*
2  * Copyright (C) 2014 Red Hat, Inc.
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  * Authors : Madhu Venugopal, Brent Salisbury, Srini Seetharaman
9  */
10 package org.opendaylight.ovsdb.utils.mdsal.openflow;
11
12 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
13 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCaseBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCaseBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.DstChoice;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpShaCaseBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpThaCaseBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIpv4DstCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpOpCaseBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpSpaCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpTpaCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfEthDstCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegMoveNodesNodeGroupBucketsBucketActionsCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionOutputRegNodesNodeTableFlowApplyActionsCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegMoveNodesNodeTableFlowApplyActionsCaseBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputReg;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputRegBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoadBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.nx.reg.load.DstBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMove;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMoveBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.SrcBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.SrcChoice;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpShaCaseBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCaseBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfArpSpaCaseBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfEthSrcCaseBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.action.rev140421.OfjNxHashFields;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.action.rev140421.OfjNxMpAlgorithm;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionMultipathNodesNodeTableFlowApplyActionsCaseBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionResubmitNodesNodeTableFlowApplyActionsCaseBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNsiNodesNodeTableFlowApplyActionsCaseBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNspNodesNodeTableFlowApplyActionsCaseBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.multipath.grouping.NxMultipath;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.multipath.grouping.NxMultipathBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.resubmit.grouping.NxResubmit;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.resubmit.grouping.NxResubmitBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsi.grouping.NxSetNsi;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsi.grouping.NxSetNsiBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsp.grouping.NxSetNsp;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.set.nsp.grouping.NxSetNspBuilder;
76
77 import com.google.common.net.InetAddresses;
78
79 import java.math.BigInteger;
80
81 public final class ActionUtils {
82     public static Action dropAction() {
83         return new DropActionCaseBuilder()
84             .setDropAction(new DropActionBuilder()
85                 .build())
86             .build();
87     }
88
89     public static Action outputAction(NodeConnectorId id) {
90         return new OutputActionCaseBuilder()
91             .setOutputAction(new OutputActionBuilder()
92                 .setOutputNodeConnector(new Uri(id.getValue()))
93                 .build())
94             .build();
95     }
96
97     public static Action groupAction(Long id) {
98         return new GroupActionCaseBuilder()
99             .setGroupAction(new GroupActionBuilder()
100                 .setGroupId(id)
101                 .build())
102             .build();
103     }
104
105     public static Action setDlSrcAction(MacAddress mac) {
106         return new SetDlSrcActionCaseBuilder()
107             .setSetDlSrcAction(new SetDlSrcActionBuilder()
108                 .setAddress(mac)
109                 .build())
110             .build();
111     }
112
113     public static Action setDlDstAction(MacAddress mac) {
114         return new SetDlDstActionCaseBuilder()
115             .setSetDlDstAction(new SetDlDstActionBuilder()
116                 .setAddress(mac)
117                 .build())
118             .build();
119     }
120
121     public static Action setNwSrcAction(Address ip) {
122         return new SetNwSrcActionCaseBuilder()
123             .setSetNwSrcAction(new SetNwSrcActionBuilder()
124                 .setAddress(ip)
125                 .build())
126             .build();
127     }
128
129     public static Action setNwDstAction(Address ip) {
130         return new SetNwDstActionCaseBuilder()
131             .setSetNwDstAction(new SetNwDstActionBuilder()
132                 .setAddress(ip)
133                 .build())
134             .build();
135     }
136
137     public static Action decNwTtlAction() {
138         return new DecNwTtlCaseBuilder()
139             .setDecNwTtl(new DecNwTtlBuilder()
140                 .build())
141             .build();
142     }
143
144     public static Action nxLoadRegAction(DstChoice dstChoice,
145                                          BigInteger value,
146                                          int endOffset,
147                                          boolean groupBucket) {
148         NxRegLoad r = new NxRegLoadBuilder()
149             .setDst(new DstBuilder()
150                 .setDstChoice(dstChoice)
151                 .setStart(Integer.valueOf(0))
152                 .setEnd(Integer.valueOf(endOffset))
153                 .build())
154             .setValue(value)
155             .build();
156         if (groupBucket) {
157             return new NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder()
158                 .setNxRegLoad(r).build();
159         } else {
160             return new NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder()
161                 .setNxRegLoad(r).build();
162         }
163     }
164
165     public static Action nxLoadRegAction(DstChoice dstChoice,
166                                          BigInteger value) {
167         return nxLoadRegAction(dstChoice, value, 31, false);
168     }
169
170     public static Action nxLoadRegAction(Class<? extends NxmNxReg> reg,
171                                          BigInteger value) {
172         return nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(reg).build(),
173                                value);
174     }
175
176     public static Action nxLoadTunIPv4Action(String ipAddress,
177                                              boolean groupBucket) {
178         int ip = InetAddresses.coerceToInteger(InetAddresses.forString(ipAddress));
179         long ipl = ip & 0xffffffffL;
180         return nxLoadRegAction(new DstNxTunIpv4DstCaseBuilder()
181                                     .setNxTunIpv4Dst(Boolean.TRUE).build(),
182                                BigInteger.valueOf(ipl),
183                                31,
184                                groupBucket);
185     }
186
187     public static Action nxLoadArpOpAction(BigInteger value) {
188         return nxLoadRegAction(new DstOfArpOpCaseBuilder()
189             .setOfArpOp(Boolean.TRUE).build(), value, 15, false);
190     }
191
192     public static Action nxLoadArpShaAction(MacAddress macAddress) {
193         return nxLoadArpShaAction(BigInteger.valueOf(toLong(macAddress)));
194     }
195     public static Action nxLoadArpShaAction(BigInteger value) {
196         return nxLoadRegAction(new DstNxArpShaCaseBuilder()
197             .setNxArpSha(Boolean.TRUE).build(), value, 47, false);
198     }
199
200     public static Action nxLoadArpSpaAction(BigInteger value) {
201         return nxLoadRegAction(new DstOfArpSpaCaseBuilder()
202             .setOfArpSpa(Boolean.TRUE).build(), value);
203     }
204
205     public static Action nxLoadArpSpaAction(String ipAddress) {
206         int ip = InetAddresses.coerceToInteger(InetAddresses.forString(ipAddress));
207         long ipl = ip & 0xffffffffL;
208         return nxLoadArpSpaAction(BigInteger.valueOf(ipl));
209     }
210
211     public static Action nxMoveRegAction(SrcChoice srcChoice,
212                                          DstChoice dstChoice,
213                                          int endOffset,
214                                          boolean groupBucket) {
215         NxRegMove r = new NxRegMoveBuilder()
216             .setSrc(new SrcBuilder()
217                 .setSrcChoice(srcChoice)
218                 .setStart(Integer.valueOf(0))
219                 .setEnd(Integer.valueOf(endOffset))
220                 .build())
221             .setDst(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.DstBuilder()
222                 .setDstChoice(dstChoice)
223                 .setStart(Integer.valueOf(0))
224                 .setEnd(Integer.valueOf(endOffset))
225                 .build())
226             .build();
227         if (groupBucket) {
228             return new NxActionRegMoveNodesNodeGroupBucketsBucketActionsCaseBuilder()
229                 .setNxRegMove(r).build();
230         } else {
231             return new NxActionRegMoveNodesNodeTableFlowApplyActionsCaseBuilder()
232                 .setNxRegMove(r).build();
233         }
234     }
235
236     public static Action nxMoveRegAction(SrcChoice srcChoice,
237                                          DstChoice dstChoice) {
238         return nxMoveRegAction(srcChoice, dstChoice, 31, false);
239     }
240
241     public static Action nxMoveRegTunIdAction(Class<? extends NxmNxReg> src,
242                                               boolean groupBucket) {
243         return nxMoveRegAction(new SrcNxRegCaseBuilder()
244                                     .setNxReg(src).build(),
245                                new DstNxTunIdCaseBuilder()
246                                    .setNxTunId(Boolean.TRUE).build(),
247                                31,
248                                groupBucket);
249     }
250
251     public static Action nxMoveArpShaToArpThaAction() {
252         return nxMoveRegAction(new SrcNxArpShaCaseBuilder()
253                                    .setNxArpSha(Boolean.TRUE).build(),
254                                new DstNxArpThaCaseBuilder()
255                                    .setNxArpTha(Boolean.TRUE).build(),
256                                47, false);
257     }
258
259     public static Action nxMoveEthSrcToEthDstAction() {
260         return nxMoveRegAction(new SrcOfEthSrcCaseBuilder()
261                                    .setOfEthSrc(Boolean.TRUE).build(),
262                                new DstOfEthDstCaseBuilder()
263                                    .setOfEthDst(Boolean.TRUE).build(),
264                                47, false);
265     }
266
267     public static Action nxMoveArpSpaToArpTpaAction() {
268         return nxMoveRegAction(new SrcOfArpSpaCaseBuilder()
269                                    .setOfArpSpa(Boolean.TRUE).build(),
270                                new DstOfArpTpaCaseBuilder()
271                                    .setOfArpTpa(Boolean.TRUE).build());
272     }
273
274     public static Action nxOutputRegAction(SrcChoice srcChoice) {
275         NxOutputReg r = new NxOutputRegBuilder()
276             .setSrc(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.nx.output.reg.SrcBuilder()
277                 .setSrcChoice(srcChoice)
278                 .setOfsNbits(Integer.valueOf(31))
279                 .build())
280             .setMaxLen(Integer.valueOf(0xffff))
281             .build();
282         return new NxActionOutputRegNodesNodeTableFlowApplyActionsCaseBuilder()
283             .setNxOutputReg(r).build();
284     }
285
286     public static Action nxOutputRegAction(Class<? extends NxmNxReg> reg) {
287         return nxOutputRegAction(new SrcNxRegCaseBuilder().setNxReg(reg).build());
288     }
289
290     public static Action nxResubmitAction(Integer inPort, Short table) {
291         NxResubmitBuilder builder = new NxResubmitBuilder();
292         if (inPort != null) {
293             builder.setInPort(inPort);
294         }
295         if (table != null) {
296             builder.setTable(table);
297         }
298         NxResubmit r = builder.build();
299         return new NxActionResubmitNodesNodeTableFlowApplyActionsCaseBuilder().setNxResubmit(r).build();
300     }
301
302     public static Action nxSetNspAction(Long nsp) {
303         NxSetNspBuilder builder = new NxSetNspBuilder();
304         if (nsp != null) {
305             builder.setNsp(nsp);
306         }
307         NxSetNsp r = builder.build();
308         return new NxActionSetNspNodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNsp(r).build();
309     }
310
311     public static Action nxSetNsiAction(Short nsp) {
312         NxSetNsiBuilder builder = new NxSetNsiBuilder();
313         if (nsp != null) {
314             builder.setNsi(nsp);
315         }
316         NxSetNsi r = builder.build();
317         return new NxActionSetNsiNodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNsi(r).build();
318     }
319
320     public static Action nxMultipathAction(OfjNxHashFields fields, Integer basis,
321             OfjNxMpAlgorithm algorithm, Integer maxLink, Long arg, DstChoice dstChoice,
322             Integer start, Integer end) {
323         NxMultipath r = new NxMultipathBuilder()
324             .setFields(fields)
325             .setBasis(basis)
326             .setAlgorithm(algorithm)
327             .setMaxLink(maxLink)
328             .setArg(arg)
329             .setDst(new org.opendaylight.yang.gen.v1.urn.opendaylight.ovs.nx.sal.action.rev140714.nx.action.multipath.grouping.nx.multipath.DstBuilder()
330                 .setDstChoice(dstChoice)
331                 .setStart(start)
332                 .setEnd(end)
333                 .build())
334             .build();
335         return new NxActionMultipathNodesNodeTableFlowApplyActionsCaseBuilder().setNxMultipath(r).build();
336     }
337
338     /**
339      * Accepts a MAC address and returns the corresponding long, where the
340      * MAC bytes are set on the lower order bytes of the long.
341      * @param macAddress
342      * @return a long containing the mac address bytes
343      */
344     public static long toLong(byte[] macAddress) {
345         long mac = 0;
346         for (int i = 0; i < 6; i++) {
347             long t = (macAddress[i] & 0xffL) << ((5-i)*8);
348             mac |= t;
349         }
350         return mac;
351     }
352
353     /**
354      * Accepts a MAC address of the form 00:aa:11:bb:22:cc, case does not
355      * matter, and returns the corresponding long, where the MAC bytes are set
356      * on the lower order bytes of the long.
357      *
358      * @param macAddress
359      *            in String format
360      * @return a long containing the mac address bytes
361      */
362     public static long toLong(MacAddress macAddress) {
363         return toLong(toMACAddress(macAddress.getValue()));
364     }
365
366     /**
367      * Accepts a MAC address of the form 00:aa:11:bb:22:cc, case does not
368      * matter, and returns a corresponding byte[].
369      * @param macAddress
370      * @return
371      */
372     public static byte[] toMACAddress(String macAddress) {
373         final String HEXES = "0123456789ABCDEF";
374         byte[] address = new byte[6];
375         String[] macBytes = macAddress.split(":");
376         if (macBytes.length != 6)
377             throw new IllegalArgumentException(
378                     "Specified MAC Address must contain 12 hex digits" +
379                     " separated pairwise by :'s.");
380         for (int i = 0; i < 6; ++i) {
381             address[i] = (byte) ((HEXES.indexOf(macBytes[i].toUpperCase()
382                                                         .charAt(0)) << 4) | HEXES.indexOf(macBytes[i].toUpperCase()
383                                                                                                   .charAt(1)));
384         }
385         return address;
386     }
387 }