Carmelo Cascone
Committed by Thomas Vachuska

Various bmv2 changes to reflect onos-bmv2 v1.0.0 (onos1.6 cherry-pick)

Most notably:
- Updated repo URL and commit ID to official onos-bmv2 fork
- Removed ugly string-based table dump parser, now there's
	a proper API to retrieve table entries (added support in
	Bmv2DeviceAgent)
- Removed unused arguments in packet-in API

Change-Id: I5ff0948eb8fec5283a085913496c187e7b278d8d
...@@ -118,10 +118,14 @@ public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour implement ...@@ -118,10 +118,14 @@ public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour implement
118 return; 118 return;
119 } 119 }
120 120
121 - // Bmv2 doesn't support proper polling for table entries, but only a string based table dump. 121 + List<Bmv2ParsedTableEntry> installedEntries;
122 - // The trick here is to first dump the entries currently installed in the device for a given table, 122 + try {
123 - // and then query a service for the corresponding, previously applied, flow rule. 123 + installedEntries = deviceAgent.getTableEntries(table.name());
124 - List<Bmv2ParsedTableEntry> installedEntries = tableEntryService.getTableEntries(deviceId, table.name()); 124 + } catch (Bmv2RuntimeException e) {
125 + log.warn("Failed to get table entries of table {} of {}: {}", table.name(), deviceId, e.explain());
126 + return;
127 + }
128 +
125 installedEntries.forEach(parsedEntry -> { 129 installedEntries.forEach(parsedEntry -> {
126 Bmv2TableEntryReference entryRef = new Bmv2TableEntryReference(deviceId, 130 Bmv2TableEntryReference entryRef = new Bmv2TableEntryReference(deviceId,
127 table.name(), 131 table.name(),
...@@ -309,7 +313,7 @@ public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour implement ...@@ -309,7 +313,7 @@ public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour implement
309 private void forceRemove(Bmv2DeviceAgent agent, String tableName, Bmv2MatchKey matchKey) 313 private void forceRemove(Bmv2DeviceAgent agent, String tableName, Bmv2MatchKey matchKey)
310 throws Bmv2RuntimeException { 314 throws Bmv2RuntimeException {
311 // Find the entryID (expensive call!) 315 // Find the entryID (expensive call!)
312 - for (Bmv2ParsedTableEntry pEntry : tableEntryService.getTableEntries(agent.deviceId(), tableName)) { 316 + for (Bmv2ParsedTableEntry pEntry : agent.getTableEntries(tableName)) {
313 if (pEntry.matchKey().equals(matchKey)) { 317 if (pEntry.matchKey().equals(matchKey)) {
314 // Remove entry and drop exceptions. 318 // Remove entry and drop exceptions.
315 silentlyRemove(agent, tableName, pEntry.entryId()); 319 silentlyRemove(agent, tableName, pEntry.entryId());
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
16 ~ limitations under the License. 16 ~ limitations under the License.
17 --> 17 -->
18 <drivers> 18 <drivers>
19 - <driver name="bmv2-thrift" manufacturer="p4.org" hwVersion="bmv2" swVersion="n/a"> 19 + <driver name="bmv2-thrift" manufacturer="p4.org" hwVersion="bmv2" swVersion="1.0.0">
20 <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery" 20 <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
21 impl="org.onosproject.drivers.bmv2.Bmv2DeviceDescriptionDiscovery"/> 21 impl="org.onosproject.drivers.bmv2.Bmv2DeviceDescriptionDiscovery"/>
22 <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable" 22 <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
......
...@@ -37,7 +37,7 @@ public final class Bmv2Device { ...@@ -37,7 +37,7 @@ public final class Bmv2Device {
37 public static final String PROTOCOL = "bmv2-thrift"; 37 public static final String PROTOCOL = "bmv2-thrift";
38 public static final String MANUFACTURER = "p4.org"; 38 public static final String MANUFACTURER = "p4.org";
39 public static final String HW_VERSION = "bmv2"; 39 public static final String HW_VERSION = "bmv2";
40 - public static final String SW_VERSION = N_A; 40 + public static final String SW_VERSION = "1.0.0";
41 public static final String SERIAL_NUMBER = N_A; 41 public static final String SERIAL_NUMBER = N_A;
42 42
43 private final String thriftServerHost; 43 private final String thriftServerHost;
......
...@@ -21,6 +21,7 @@ import org.onlab.util.ImmutableByteSequence; ...@@ -21,6 +21,7 @@ import org.onlab.util.ImmutableByteSequence;
21 import org.onosproject.net.DeviceId; 21 import org.onosproject.net.DeviceId;
22 22
23 import java.util.Collection; 23 import java.util.Collection;
24 +import java.util.List;
24 25
25 /** 26 /**
26 * An agent to control a BMv2 device. 27 * An agent to control a BMv2 device.
...@@ -87,13 +88,13 @@ public interface Bmv2DeviceAgent { ...@@ -87,13 +88,13 @@ public interface Bmv2DeviceAgent {
87 Collection<Bmv2PortInfo> getPortsInfo() throws Bmv2RuntimeException; 88 Collection<Bmv2PortInfo> getPortsInfo() throws Bmv2RuntimeException;
88 89
89 /** 90 /**
90 - * Return a string representation of the given table content. 91 + * Returns a list of table entries installed in the given table.
91 * 92 *
92 - * @param tableName string value of table name 93 + * @param tableName a string value
93 - * @return table string dump 94 + * @return a list of parsed table entries
94 * @throws Bmv2RuntimeException if any error occurs 95 * @throws Bmv2RuntimeException if any error occurs
95 */ 96 */
96 - String dumpTable(String tableName) throws Bmv2RuntimeException; 97 + List<Bmv2ParsedTableEntry> getTableEntries(String tableName) throws Bmv2RuntimeException;
97 98
98 /** 99 /**
99 * Requests the device to transmit a given byte sequence over the given port. 100 * Requests the device to transmit a given byte sequence over the given port.
......
...@@ -20,24 +20,27 @@ import com.google.common.base.MoreObjects; ...@@ -20,24 +20,27 @@ import com.google.common.base.MoreObjects;
20 import com.google.common.base.Objects; 20 import com.google.common.base.Objects;
21 21
22 /** 22 /**
23 - * Representation of a table entry obtained by parsing a BMv2 table dump. 23 + * Representation of a table entry installed on a BMv2 device.
24 */ 24 */
25 public final class Bmv2ParsedTableEntry { 25 public final class Bmv2ParsedTableEntry {
26 private final long entryId; 26 private final long entryId;
27 private final Bmv2MatchKey matchKey; 27 private final Bmv2MatchKey matchKey;
28 private final Bmv2Action action; 28 private final Bmv2Action action;
29 + private final int priority;
29 30
30 /** 31 /**
31 * Creates a new parsed table entry. 32 * Creates a new parsed table entry.
32 * 33 *
33 - * @param entryId an entry ID 34 + * @param entryId a long value
34 * @param matchKey a match key 35 * @param matchKey a match key
35 * @param action an action 36 * @param action an action
37 + * @param priority an integer value
36 */ 38 */
37 - public Bmv2ParsedTableEntry(long entryId, Bmv2MatchKey matchKey, Bmv2Action action) { 39 + public Bmv2ParsedTableEntry(long entryId, Bmv2MatchKey matchKey, Bmv2Action action, int priority) {
38 this.entryId = entryId; 40 this.entryId = entryId;
39 this.matchKey = matchKey; 41 this.matchKey = matchKey;
40 this.action = action; 42 this.action = action;
43 + this.priority = priority;
41 } 44 }
42 45
43 /** 46 /**
...@@ -67,9 +70,18 @@ public final class Bmv2ParsedTableEntry { ...@@ -67,9 +70,18 @@ public final class Bmv2ParsedTableEntry {
67 return action; 70 return action;
68 } 71 }
69 72
73 + /**
74 + * Returns the priority.
75 + *
76 + * @return an integer value
77 + */
78 + public int getPriority() {
79 + return priority;
80 + }
81 +
70 @Override 82 @Override
71 public int hashCode() { 83 public int hashCode() {
72 - return Objects.hashCode(entryId, matchKey, action); 84 + return Objects.hashCode(entryId, matchKey, action, priority);
73 } 85 }
74 86
75 @Override 87 @Override
...@@ -83,7 +95,8 @@ public final class Bmv2ParsedTableEntry { ...@@ -83,7 +95,8 @@ public final class Bmv2ParsedTableEntry {
83 final Bmv2ParsedTableEntry other = (Bmv2ParsedTableEntry) obj; 95 final Bmv2ParsedTableEntry other = (Bmv2ParsedTableEntry) obj;
84 return Objects.equal(this.entryId, other.entryId) 96 return Objects.equal(this.entryId, other.entryId)
85 && Objects.equal(this.matchKey, other.matchKey) 97 && Objects.equal(this.matchKey, other.matchKey)
86 - && Objects.equal(this.action, other.action); 98 + && Objects.equal(this.action, other.action)
99 + && Objects.equal(this.priority, other.priority);
87 } 100 }
88 101
89 @Override 102 @Override
......
...@@ -29,11 +29,7 @@ public interface Bmv2PacketListener { ...@@ -29,11 +29,7 @@ public interface Bmv2PacketListener {
29 * 29 *
30 * @param device the BMv2 device that originated the message 30 * @param device the BMv2 device that originated the message
31 * @param inputPort the device port where the packet was received 31 * @param inputPort the device port where the packet was received
32 - * @param reason a reason code
33 - * @param tableId the ID of table that originated this packet-in
34 - * @param contextId the ID of the BMv2 context where the packet-in was originated
35 * @param packet the packet raw data 32 * @param packet the packet raw data
36 */ 33 */
37 - void handlePacketIn(Bmv2Device device, int inputPort, long reason, int tableId, int contextId, 34 + void handlePacketIn(Bmv2Device device, int inputPort, ImmutableByteSequence packet);
38 - ImmutableByteSequence packet);
39 } 35 }
......
...@@ -19,11 +19,7 @@ package org.onosproject.bmv2.api.service; ...@@ -19,11 +19,7 @@ package org.onosproject.bmv2.api.service;
19 19
20 import org.onosproject.bmv2.api.context.Bmv2FlowRuleTranslator; 20 import org.onosproject.bmv2.api.context.Bmv2FlowRuleTranslator;
21 import org.onosproject.bmv2.api.runtime.Bmv2FlowRuleWrapper; 21 import org.onosproject.bmv2.api.runtime.Bmv2FlowRuleWrapper;
22 -import org.onosproject.bmv2.api.runtime.Bmv2ParsedTableEntry;
23 import org.onosproject.bmv2.api.runtime.Bmv2TableEntryReference; 22 import org.onosproject.bmv2.api.runtime.Bmv2TableEntryReference;
24 -import org.onosproject.net.DeviceId;
25 -
26 -import java.util.List;
27 23
28 /** 24 /**
29 * A service for managing BMv2 table entries. 25 * A service for managing BMv2 table entries.
...@@ -38,16 +34,6 @@ public interface Bmv2TableEntryService { ...@@ -38,16 +34,6 @@ public interface Bmv2TableEntryService {
38 Bmv2FlowRuleTranslator getFlowRuleTranslator(); 34 Bmv2FlowRuleTranslator getFlowRuleTranslator();
39 35
40 /** 36 /**
41 - * Returns a list of table entries installed in the given device and table. The table entries returned are the
42 - * result of a table dump parse.
43 - *
44 - * @param deviceId a device id
45 - * @param tableName a table name
46 - * @return a list of parsed table entries
47 - */
48 - List<Bmv2ParsedTableEntry> getTableEntries(DeviceId deviceId, String tableName);
49 -
50 - /**
51 * Binds the given ONOS flow rule with a BMv2 table entry reference. 37 * Binds the given ONOS flow rule with a BMv2 table entry reference.
52 * 38 *
53 * @param entryRef a table entry reference 39 * @param entryRef a table entry reference
......
...@@ -244,7 +244,7 @@ public class Bmv2ControllerImpl implements Bmv2Controller { ...@@ -244,7 +244,7 @@ public class Bmv2ControllerImpl implements Bmv2Controller {
244 } 244 }
245 245
246 @Override 246 @Override
247 - public void packetIn(int port, long reason, int tableId, int contextId, ByteBuffer packet) { 247 + public void packet_in(int port, ByteBuffer packet) {
248 if (remoteDevice == null) { 248 if (remoteDevice == null) {
249 log.debug("Received packet-in, but the remote device is still unknown. Need a hello first..."); 249 log.debug("Received packet-in, but the remote device is still unknown. Need a hello first...");
250 return; 250 return;
...@@ -256,9 +256,6 @@ public class Bmv2ControllerImpl implements Bmv2Controller { ...@@ -256,9 +256,6 @@ public class Bmv2ControllerImpl implements Bmv2Controller {
256 packetListeners.forEach( 256 packetListeners.forEach(
257 l -> executorService.execute(() -> l.handlePacketIn(remoteDevice, 257 l -> executorService.execute(() -> l.handlePacketIn(remoteDevice,
258 port, 258 port,
259 - reason,
260 - tableId,
261 - contextId,
262 ImmutableByteSequence.copyFrom(packet)))); 259 ImmutableByteSequence.copyFrom(packet))));
263 } 260 }
264 } 261 }
......
...@@ -26,11 +26,14 @@ import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent; ...@@ -26,11 +26,14 @@ import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent;
26 import org.onosproject.bmv2.api.runtime.Bmv2ExactMatchParam; 26 import org.onosproject.bmv2.api.runtime.Bmv2ExactMatchParam;
27 import org.onosproject.bmv2.api.runtime.Bmv2LpmMatchParam; 27 import org.onosproject.bmv2.api.runtime.Bmv2LpmMatchParam;
28 import org.onosproject.bmv2.api.runtime.Bmv2MatchKey; 28 import org.onosproject.bmv2.api.runtime.Bmv2MatchKey;
29 +import org.onosproject.bmv2.api.runtime.Bmv2MatchParam;
30 +import org.onosproject.bmv2.api.runtime.Bmv2ParsedTableEntry;
29 import org.onosproject.bmv2.api.runtime.Bmv2PortInfo; 31 import org.onosproject.bmv2.api.runtime.Bmv2PortInfo;
30 import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException; 32 import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
31 import org.onosproject.bmv2.api.runtime.Bmv2TableEntry; 33 import org.onosproject.bmv2.api.runtime.Bmv2TableEntry;
32 import org.onosproject.bmv2.api.runtime.Bmv2TernaryMatchParam; 34 import org.onosproject.bmv2.api.runtime.Bmv2TernaryMatchParam;
33 import org.onosproject.bmv2.api.runtime.Bmv2ValidMatchParam; 35 import org.onosproject.bmv2.api.runtime.Bmv2ValidMatchParam;
36 +import org.onosproject.bmv2.thriftapi.BmActionEntry;
34 import org.onosproject.bmv2.thriftapi.BmAddEntryOptions; 37 import org.onosproject.bmv2.thriftapi.BmAddEntryOptions;
35 import org.onosproject.bmv2.thriftapi.BmCounterValue; 38 import org.onosproject.bmv2.thriftapi.BmCounterValue;
36 import org.onosproject.bmv2.thriftapi.BmMatchParam; 39 import org.onosproject.bmv2.thriftapi.BmMatchParam;
...@@ -39,6 +42,7 @@ import org.onosproject.bmv2.thriftapi.BmMatchParamLPM; ...@@ -39,6 +42,7 @@ import org.onosproject.bmv2.thriftapi.BmMatchParamLPM;
39 import org.onosproject.bmv2.thriftapi.BmMatchParamTernary; 42 import org.onosproject.bmv2.thriftapi.BmMatchParamTernary;
40 import org.onosproject.bmv2.thriftapi.BmMatchParamType; 43 import org.onosproject.bmv2.thriftapi.BmMatchParamType;
41 import org.onosproject.bmv2.thriftapi.BmMatchParamValid; 44 import org.onosproject.bmv2.thriftapi.BmMatchParamValid;
45 +import org.onosproject.bmv2.thriftapi.BmMtEntry;
42 import org.onosproject.bmv2.thriftapi.SimpleSwitch; 46 import org.onosproject.bmv2.thriftapi.SimpleSwitch;
43 import org.onosproject.bmv2.thriftapi.Standard; 47 import org.onosproject.bmv2.thriftapi.Standard;
44 import org.onosproject.net.DeviceId; 48 import org.onosproject.net.DeviceId;
...@@ -50,6 +54,7 @@ import java.util.Collection; ...@@ -50,6 +54,7 @@ import java.util.Collection;
50 import java.util.List; 54 import java.util.List;
51 import java.util.stream.Collectors; 55 import java.util.stream.Collectors;
52 56
57 +import static org.onlab.util.ImmutableByteSequence.copyFrom;
53 import static org.onosproject.bmv2.ctl.Bmv2TExceptionParser.parseTException; 58 import static org.onosproject.bmv2.ctl.Bmv2TExceptionParser.parseTException;
54 59
55 /** 60 /**
...@@ -214,19 +219,71 @@ public final class Bmv2DeviceThriftClient implements Bmv2DeviceAgent { ...@@ -214,19 +219,71 @@ public final class Bmv2DeviceThriftClient implements Bmv2DeviceAgent {
214 } 219 }
215 220
216 @Override 221 @Override
217 - public String dumpTable(String tableName) throws Bmv2RuntimeException { 222 + public List<Bmv2ParsedTableEntry> getTableEntries(String tableName) throws Bmv2RuntimeException {
218 223
219 - log.debug("Retrieving table dump... > deviceId={}, tableName={}", deviceId, tableName); 224 + log.debug("Retrieving table entries... > deviceId={}, tableName={}", deviceId, tableName);
220 225
226 + List<BmMtEntry> bmEntries;
221 try { 227 try {
222 - String dump = standardClient.bm_dump_table(CONTEXT_ID, tableName); 228 + bmEntries = standardClient.bm_mt_get_entries(CONTEXT_ID, tableName);
223 - log.debug("Table dump retrieved! > deviceId={}, tableName={}", deviceId, tableName);
224 - return dump;
225 } catch (TException e) { 229 } catch (TException e) {
226 - log.debug("Exception while retrieving table dump: {} > deviceId={}, tableName={}", 230 + log.debug("Exception while retrieving table entries: {} > deviceId={}, tableName={}",
227 e, deviceId, tableName); 231 e, deviceId, tableName);
228 throw parseTException(e); 232 throw parseTException(e);
229 } 233 }
234 +
235 + List<Bmv2ParsedTableEntry> parsedEntries = Lists.newArrayList();
236 +
237 + entryLoop:
238 + for (BmMtEntry bmEntry : bmEntries) {
239 +
240 + Bmv2MatchKey.Builder matchKeyBuilder = Bmv2MatchKey.builder();
241 + for (BmMatchParam bmParam : bmEntry.getMatch_key()) {
242 + Bmv2MatchParam param;
243 + switch (bmParam.getType()) {
244 + case EXACT:
245 + param = new Bmv2ExactMatchParam(copyFrom(bmParam.getExact().getKey()));
246 + break;
247 + case LPM:
248 + param = new Bmv2LpmMatchParam(copyFrom(bmParam.getLpm().getKey()),
249 + bmParam.getLpm().getPrefix_length());
250 + break;
251 + case TERNARY:
252 + param = new Bmv2TernaryMatchParam(copyFrom(bmParam.getTernary().getKey()),
253 + copyFrom(bmParam.getTernary().getMask()));
254 + break;
255 + case VALID:
256 + param = new Bmv2ValidMatchParam(bmParam.getValid().isKey());
257 + break;
258 + default:
259 + log.warn("Parsing of match type {} unsupported, skipping table entry.",
260 + bmParam.getType().name());
261 + continue entryLoop;
262 + }
263 + matchKeyBuilder.add(param);
264 + }
265 +
266 + Bmv2Action.Builder actionBuilder = Bmv2Action.builder();
267 + BmActionEntry bmActionEntry = bmEntry.getAction_entry();
268 + switch (bmActionEntry.getAction_type()) {
269 + case ACTION_DATA:
270 + actionBuilder.withName(bmActionEntry.getAction_name());
271 + bmActionEntry.getAction_data()
272 + .stream()
273 + .map(ImmutableByteSequence::copyFrom)
274 + .forEach(actionBuilder::addParameter);
275 + break;
276 + default:
277 + log.warn("Parsing of action action type {} unsupported, skipping table entry.",
278 + bmActionEntry.getAction_type().name());
279 + continue entryLoop;
280 + }
281 +
282 + parsedEntries.add(new Bmv2ParsedTableEntry(bmEntry.getEntry_handle(), matchKeyBuilder.build(),
283 + actionBuilder.build(), bmEntry.getOptions().getPriority()));
284 + }
285 +
286 + return parsedEntries;
230 } 287 }
231 288
232 @Override 289 @Override
...@@ -236,7 +293,7 @@ public final class Bmv2DeviceThriftClient implements Bmv2DeviceAgent { ...@@ -236,7 +293,7 @@ public final class Bmv2DeviceThriftClient implements Bmv2DeviceAgent {
236 293
237 try { 294 try {
238 295
239 - simpleSwitchClient.push_packet(portNumber, ByteBuffer.wrap(packet.asArray())); 296 + simpleSwitchClient.packet_out(portNumber, ByteBuffer.wrap(packet.asArray()));
240 log.debug("Packet transmission requested! > portNumber={}, packetSize={}", portNumber, packet.size()); 297 log.debug("Packet transmission requested! > portNumber={}, packetSize={}", portNumber, packet.size());
241 } catch (TException e) { 298 } catch (TException e) {
242 log.debug("Exception while requesting packet transmission: {} > portNumber={}, packetSize={}", 299 log.debug("Exception while requesting packet transmission: {} > portNumber={}, packetSize={}",
......
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.bmv2.ctl;
18 -
19 -import com.google.common.cache.CacheBuilder;
20 -import com.google.common.cache.CacheLoader;
21 -import com.google.common.cache.CacheStats;
22 -import com.google.common.cache.LoadingCache;
23 -import com.google.common.collect.Lists;
24 -import org.apache.commons.lang3.tuple.Pair;
25 -import org.onlab.util.HexString;
26 -import org.onlab.util.ImmutableByteSequence;
27 -import org.onlab.util.SharedScheduledExecutors;
28 -import org.onosproject.bmv2.api.context.Bmv2ActionModel;
29 -import org.onosproject.bmv2.api.context.Bmv2Configuration;
30 -import org.onosproject.bmv2.api.runtime.Bmv2Action;
31 -import org.onosproject.bmv2.api.runtime.Bmv2ExactMatchParam;
32 -import org.onosproject.bmv2.api.runtime.Bmv2LpmMatchParam;
33 -import org.onosproject.bmv2.api.runtime.Bmv2MatchKey;
34 -import org.onosproject.bmv2.api.runtime.Bmv2ParsedTableEntry;
35 -import org.onosproject.bmv2.api.runtime.Bmv2TernaryMatchParam;
36 -import org.slf4j.Logger;
37 -import org.slf4j.LoggerFactory;
38 -
39 -import java.util.Arrays;
40 -import java.util.Collections;
41 -import java.util.List;
42 -import java.util.Optional;
43 -import java.util.concurrent.ExecutionException;
44 -import java.util.concurrent.TimeUnit;
45 -import java.util.regex.Matcher;
46 -import java.util.regex.Pattern;
47 -import java.util.stream.Collectors;
48 -
49 -import static com.google.common.base.Preconditions.checkNotNull;
50 -import static org.onosproject.bmv2.api.utils.Bmv2TranslatorUtils.fitByteSequence;
51 -import static org.onosproject.bmv2.api.utils.Bmv2TranslatorUtils.ByteSequenceFitException;
52 -
53 -/**
54 - * BMv2 table dump parser.
55 - */
56 -public final class Bmv2TableDumpParser {
57 -
58 - // Examples of a BMv2 table dump can be found in Bmv2TableDumpParserTest
59 -
60 - // 1: entry id, 2: match string, 3: action string
61 - private static final String ENTRY_PATTERN_REGEX = "(\\d+): (.*) => (.*)";
62 - // 1: match values, 2: masks
63 - private static final String MATCH_TERNARY_PATTERN_REGEX = "([0-9a-fA-F ]+) &&& ([0-9a-fA-F ]+)";
64 - // 1: match values, 2: masks
65 - private static final String MATCH_LPM_PATTERN_REGEX = "([0-9a-fA-F ]+) / ([0-9a-fA-F ]+)";
66 - // 1: match values
67 - private static final String MATCH_EXACT_PATTERN_REGEX = "([0-9a-fA-F ]+)";
68 - // 1: action name, 2: action params
69 - private static final String ACTION_PATTERN_REGEX = "(.+) - ?([0-9a-fA-F ,]*)";
70 -
71 - private static final Pattern ENTRY_PATTERN = Pattern.compile(ENTRY_PATTERN_REGEX);
72 - private static final Pattern MATCH_TERNARY_PATTERN = Pattern.compile(MATCH_TERNARY_PATTERN_REGEX);
73 - private static final Pattern MATCH_LPM_PATTERN = Pattern.compile(MATCH_LPM_PATTERN_REGEX);
74 - private static final Pattern MATCH_EXACT_PATTERN = Pattern.compile(MATCH_EXACT_PATTERN_REGEX);
75 - private static final Pattern ACTION_PATTERN = Pattern.compile(ACTION_PATTERN_REGEX);
76 -
77 - // Cache to avoid re-parsing known lines.
78 - // The assumption here is that entries are not updated too frequently, so that the entry id doesn't change often.
79 - // Otherwise, we should cache only the match and action strings...
80 - private static final LoadingCache<Pair<String, Bmv2Configuration>, Optional<Bmv2ParsedTableEntry>> ENTRY_CACHE =
81 - CacheBuilder.newBuilder()
82 - .expireAfterAccess(60, TimeUnit.SECONDS)
83 - .recordStats()
84 - .build(new CacheLoader<Pair<String, Bmv2Configuration>, Optional<Bmv2ParsedTableEntry>>() {
85 - @Override
86 - public Optional<Bmv2ParsedTableEntry> load(Pair<String, Bmv2Configuration> key) throws Exception {
87 - // Very expensive call.
88 - return Optional.ofNullable(parseLine(key.getLeft(), key.getRight()));
89 - }
90 - });
91 -
92 - private static final Logger log = LoggerFactory.getLogger(Bmv2TableDumpParser.class);
93 -
94 - private static final long STATS_LOG_FREQUENCY = 3; // minutes
95 -
96 - static {
97 - SharedScheduledExecutors.getSingleThreadExecutor().scheduleAtFixedRate(
98 - () -> reportStats(), 0, STATS_LOG_FREQUENCY, TimeUnit.MINUTES);
99 - }
100 -
101 - private Bmv2TableDumpParser() {
102 - // Ban constructor.
103 - }
104 -
105 - /**
106 - * Parse the given BMv2 table dump.
107 - *
108 - * @param tableDump a string value
109 - * @return a list of {@link Bmv2ParsedTableEntry}
110 - */
111 - public static List<Bmv2ParsedTableEntry> parse(String tableDump, Bmv2Configuration configuration) {
112 - checkNotNull(tableDump, "tableDump cannot be null");
113 - // Parse all lines
114 - List<Bmv2ParsedTableEntry> result = Arrays.stream(tableDump.split("\n"))
115 - .map(line -> Pair.of(line, configuration))
116 - .map(Bmv2TableDumpParser::loadFromCache)
117 - .filter(Optional::isPresent)
118 - .map(Optional::get)
119 - .collect(Collectors.toList());
120 - return result;
121 - }
122 -
123 - private static Optional<Bmv2ParsedTableEntry> loadFromCache(Pair<String, Bmv2Configuration> key) {
124 - try {
125 - return ENTRY_CACHE.get(key);
126 - } catch (ExecutionException e) {
127 - Throwable t = e.getCause();
128 - if (t instanceof Bmv2TableDumpParserException) {
129 - Bmv2TableDumpParserException parserException = (Bmv2TableDumpParserException) t;
130 - log.warn("{}", parserException.getMessage());
131 - } else {
132 - log.error("Exception while parsing table dump line", e);
133 - }
134 - return Optional.empty();
135 - }
136 - }
137 -
138 - private static void reportStats() {
139 - CacheStats stats = ENTRY_CACHE.stats();
140 - log.info("Cache stats: requestCount={}, hitRate={}, exceptionsCount={}, avgLoadPenalty={}",
141 - stats.requestCount(), stats.hitRate(), stats.loadExceptionCount(), stats.averageLoadPenalty());
142 - }
143 -
144 - private static Bmv2ParsedTableEntry parseLine(String line, Bmv2Configuration configuration)
145 - throws Bmv2TableDumpParserException {
146 - Matcher matcher = ENTRY_PATTERN.matcher(line);
147 - if (matcher.find()) {
148 - long entryId = parseEntryId(matcher, 1);
149 - String matchString = parseMatchString(matcher, 2);
150 - String actionString = parseActionString(matcher, 3);
151 - Bmv2MatchKey matchKey = parseMatchKey(matchString);
152 - Bmv2Action action = parseAction(actionString, configuration);
153 - return new Bmv2ParsedTableEntry(entryId, matchKey, action);
154 - } else {
155 - // Not a table entry
156 - return null;
157 - }
158 - }
159 -
160 - private static Long parseEntryId(Matcher matcher, int groupIdx) throws Bmv2TableDumpParserException {
161 - String str = matcher.group(groupIdx);
162 - if (str == null) {
163 - throw new Bmv2TableDumpParserException("Unable to find entry ID: " + matcher.group());
164 - }
165 - long entryId;
166 - try {
167 - entryId = Long.valueOf(str.trim());
168 - } catch (NumberFormatException e) {
169 - throw new Bmv2TableDumpParserException("Unable to parse entry id for string: " + matcher.group());
170 - }
171 - return entryId;
172 - }
173 -
174 - private static String parseMatchString(Matcher matcher, int groupIdx) throws Bmv2TableDumpParserException {
175 - String str = matcher.group(groupIdx);
176 - if (str == null) {
177 - throw new Bmv2TableDumpParserException("Unable to find match string: " + matcher.group());
178 - }
179 - return str.trim();
180 - }
181 -
182 - private static String parseActionString(Matcher matcher, int groupIdx) throws Bmv2TableDumpParserException {
183 - String str = matcher.group(groupIdx);
184 - if (str == null) {
185 - throw new Bmv2TableDumpParserException("Unable to find action string: " + matcher.group());
186 - }
187 - return str.trim();
188 - }
189 -
190 - private static Bmv2MatchKey parseMatchKey(String str) throws Bmv2TableDumpParserException {
191 -
192 - Bmv2MatchKey.Builder builder = Bmv2MatchKey.builder();
193 -
194 - // Try with ternary...
195 - Matcher matcher = MATCH_TERNARY_PATTERN.matcher(str);
196 - if (matcher.find()) {
197 - // Ternary Match.
198 - List<ImmutableByteSequence> values = parseMatchValues(matcher, 1);
199 - List<ImmutableByteSequence> masks = parseMatchMasks(matcher, 2, values);
200 - for (int i = 0; i < values.size(); i++) {
201 - builder.add(new Bmv2TernaryMatchParam(values.get(i), masks.get(i)));
202 - }
203 - return builder.build();
204 - }
205 -
206 - // FIXME: LPM match parsing broken if table key contains also a ternary match
207 - // Also it assumes the lpm parameter is the last one, which is wrong.
208 - // Try with LPM...
209 - matcher = MATCH_LPM_PATTERN.matcher(str);
210 - if (matcher.find()) {
211 - // Lpm Match.
212 - List<ImmutableByteSequence> values = parseMatchValues(matcher, 1);
213 - int prefixLength = parseLpmPrefix(matcher, 2);
214 - for (int i = 0; i < values.size() - 1; i++) {
215 - builder.add(new Bmv2ExactMatchParam(values.get(i)));
216 - }
217 - builder.add(new Bmv2LpmMatchParam(values.get(values.size() - 1), prefixLength));
218 - return builder.build();
219 - }
220 -
221 - // Try with exact...
222 - matcher = MATCH_EXACT_PATTERN.matcher(str);
223 - if (matcher.find()) {
224 - // Exact match.
225 - parseMatchValues(matcher, 1)
226 - .stream()
227 - .map(Bmv2ExactMatchParam::new)
228 - .forEach(builder::add);
229 - return builder.build();
230 - }
231 -
232 - throw new Bmv2TableDumpParserException("Unable to parse match string: " + str);
233 - }
234 -
235 - private static List<ImmutableByteSequence> parseMatchValues(Matcher matcher, int groupIdx)
236 - throws Bmv2TableDumpParserException {
237 - String matchString = matcher.group(groupIdx);
238 - if (matchString == null) {
239 - throw new Bmv2TableDumpParserException("Unable to find match params for string: " + matcher.group());
240 - }
241 - List<ImmutableByteSequence> result = Lists.newArrayList();
242 - for (String paramString : matchString.split(" ")) {
243 - byte[] bytes = HexString.fromHexString(paramString, null);
244 - result.add(ImmutableByteSequence.copyFrom(bytes));
245 - }
246 - return result;
247 - }
248 -
249 - private static List<ImmutableByteSequence> parseMatchMasks(Matcher matcher, int groupIdx,
250 - List<ImmutableByteSequence> matchParams)
251 - throws Bmv2TableDumpParserException {
252 - String maskString = matcher.group(groupIdx);
253 - if (maskString == null) {
254 - throw new Bmv2TableDumpParserException("Unable to find mask for string: " + matcher.group());
255 - }
256 - List<ImmutableByteSequence> result = Lists.newArrayList();
257 - /*
258 - Mask here is a hex string with no spaces, hence individual mask params can be derived according
259 - to given matchParam sizes.
260 - */
261 - byte[] maskBytes = HexString.fromHexString(maskString, null);
262 - int startPosition = 0;
263 - for (ImmutableByteSequence bs : matchParams) {
264 - if (startPosition + bs.size() > maskBytes.length) {
265 - throw new Bmv2TableDumpParserException("Invalid length for mask in string: " + matcher.group());
266 - }
267 - ImmutableByteSequence maskParam = ImmutableByteSequence.copyFrom(maskBytes,
268 - startPosition,
269 - startPosition + bs.size() - 1);
270 - result.add(maskParam);
271 - startPosition += bs.size();
272 - }
273 - return result;
274 - }
275 -
276 - private static int parseLpmPrefix(Matcher matcher, int groupIdx)
277 - throws Bmv2TableDumpParserException {
278 - String str = matcher.group(groupIdx);
279 - if (str == null) {
280 - throw new Bmv2TableDumpParserException("Unable to find LPM prefix for string: " + matcher.group());
281 - }
282 - // For some reason the dumped prefix has 16 bits more than the one programmed
283 - try {
284 - return Integer.valueOf(str.trim()) - 16;
285 - } catch (NumberFormatException e) {
286 - throw new Bmv2TableDumpParserException("Unable to parse LPM prefix from string: " + matcher.group());
287 - }
288 - }
289 -
290 - private static Bmv2Action parseAction(String str, Bmv2Configuration configuration)
291 - throws Bmv2TableDumpParserException {
292 - Matcher matcher = ACTION_PATTERN.matcher(str);
293 - if (matcher.find()) {
294 - String actionName = parseActionName(matcher, 1);
295 - Bmv2ActionModel actionModel = configuration.action(actionName);
296 - if (actionModel == null) {
297 - throw new Bmv2TableDumpParserException("Not such an action in configuration: " + actionName);
298 - }
299 - Bmv2Action.Builder builder = Bmv2Action.builder().withName(actionName);
300 - List<ImmutableByteSequence> actionParams = parseActionParams(matcher, 2);
301 - if (actionParams.size() != actionModel.runtimeDatas().size()) {
302 - throw new Bmv2TableDumpParserException("Invalid number of parameters for action: " + actionName);
303 - }
304 - for (int i = 0; i < actionModel.runtimeDatas().size(); i++) {
305 - try {
306 - // fit param byte-width according to configuration.
307 - builder.addParameter(fitByteSequence(actionParams.get(i),
308 - actionModel.runtimeDatas().get(i).bitWidth()));
309 - } catch (ByteSequenceFitException e) {
310 - throw new Bmv2TableDumpParserException("Unable to parse action param: " + e.toString());
311 - }
312 - }
313 - return builder.build();
314 - }
315 - throw new Bmv2TableDumpParserException("Unable to parse action string: " + str.trim());
316 - }
317 -
318 - private static String parseActionName(Matcher matcher, int groupIdx) throws Bmv2TableDumpParserException {
319 - String actionName = matcher.group(groupIdx);
320 - if (actionName == null) {
321 - throw new Bmv2TableDumpParserException("Unable to find action name for string: " + matcher.group());
322 - }
323 - return actionName.trim();
324 - }
325 -
326 - private static List<ImmutableByteSequence> parseActionParams(Matcher matcher, int groupIdx)
327 - throws Bmv2TableDumpParserException {
328 - String paramsString = matcher.group(groupIdx);
329 - if (paramsString == null) {
330 - throw new Bmv2TableDumpParserException("Unable to find action params for string: " + matcher.group());
331 - }
332 - if (paramsString.length() == 0) {
333 - return Collections.emptyList();
334 - }
335 - return Arrays.stream(paramsString.split(","))
336 - .map(String::trim)
337 - .map(s -> HexString.fromHexString(s, null))
338 - .map(ImmutableByteSequence::copyFrom)
339 - .collect(Collectors.toList());
340 - }
341 -
342 - public static class Bmv2TableDumpParserException extends Exception {
343 - public Bmv2TableDumpParserException(String msg) {
344 - super(msg);
345 - }
346 - }
347 -}
...\ No newline at end of file ...\ No newline at end of file
...@@ -23,22 +23,17 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -23,22 +23,17 @@ import org.apache.felix.scr.annotations.Reference;
23 import org.apache.felix.scr.annotations.ReferenceCardinality; 23 import org.apache.felix.scr.annotations.ReferenceCardinality;
24 import org.apache.felix.scr.annotations.Service; 24 import org.apache.felix.scr.annotations.Service;
25 import org.onlab.util.KryoNamespace; 25 import org.onlab.util.KryoNamespace;
26 -import org.onosproject.bmv2.api.context.Bmv2DeviceContext;
27 import org.onosproject.bmv2.api.context.Bmv2FlowRuleTranslator; 26 import org.onosproject.bmv2.api.context.Bmv2FlowRuleTranslator;
28 -import org.onosproject.bmv2.api.service.Bmv2DeviceContextService;
29 -import org.onosproject.bmv2.api.service.Bmv2Controller;
30 -import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent;
31 import org.onosproject.bmv2.api.runtime.Bmv2ExactMatchParam; 27 import org.onosproject.bmv2.api.runtime.Bmv2ExactMatchParam;
32 import org.onosproject.bmv2.api.runtime.Bmv2FlowRuleWrapper; 28 import org.onosproject.bmv2.api.runtime.Bmv2FlowRuleWrapper;
33 import org.onosproject.bmv2.api.runtime.Bmv2LpmMatchParam; 29 import org.onosproject.bmv2.api.runtime.Bmv2LpmMatchParam;
34 import org.onosproject.bmv2.api.runtime.Bmv2MatchKey; 30 import org.onosproject.bmv2.api.runtime.Bmv2MatchKey;
35 -import org.onosproject.bmv2.api.runtime.Bmv2ParsedTableEntry;
36 -import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
37 import org.onosproject.bmv2.api.runtime.Bmv2TableEntryReference; 31 import org.onosproject.bmv2.api.runtime.Bmv2TableEntryReference;
38 -import org.onosproject.bmv2.api.service.Bmv2TableEntryService;
39 import org.onosproject.bmv2.api.runtime.Bmv2TernaryMatchParam; 32 import org.onosproject.bmv2.api.runtime.Bmv2TernaryMatchParam;
40 import org.onosproject.bmv2.api.runtime.Bmv2ValidMatchParam; 33 import org.onosproject.bmv2.api.runtime.Bmv2ValidMatchParam;
41 -import org.onosproject.net.DeviceId; 34 +import org.onosproject.bmv2.api.service.Bmv2Controller;
35 +import org.onosproject.bmv2.api.service.Bmv2DeviceContextService;
36 +import org.onosproject.bmv2.api.service.Bmv2TableEntryService;
42 import org.onosproject.store.serializers.KryoNamespaces; 37 import org.onosproject.store.serializers.KryoNamespaces;
43 import org.onosproject.store.service.EventuallyConsistentMap; 38 import org.onosproject.store.service.EventuallyConsistentMap;
44 import org.onosproject.store.service.StorageService; 39 import org.onosproject.store.service.StorageService;
...@@ -46,9 +41,6 @@ import org.onosproject.store.service.WallClockTimestamp; ...@@ -46,9 +41,6 @@ import org.onosproject.store.service.WallClockTimestamp;
46 import org.slf4j.Logger; 41 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory; 42 import org.slf4j.LoggerFactory;
48 43
49 -import java.util.Collections;
50 -import java.util.List;
51 -
52 import static com.google.common.base.Preconditions.checkNotNull; 44 import static com.google.common.base.Preconditions.checkNotNull;
53 45
54 /** 46 /**
...@@ -107,23 +99,6 @@ public class Bmv2TableEntryServiceImpl implements Bmv2TableEntryService { ...@@ -107,23 +99,6 @@ public class Bmv2TableEntryServiceImpl implements Bmv2TableEntryService {
107 } 99 }
108 100
109 @Override 101 @Override
110 - public List<Bmv2ParsedTableEntry> getTableEntries(DeviceId deviceId, String tableName) {
111 - try {
112 - Bmv2DeviceContext context = contextService.getContext(deviceId);
113 - if (context == null) {
114 - log.warn("Unable to get table entries, found null context for {}", deviceId);
115 - return Collections.emptyList();
116 - }
117 - Bmv2DeviceAgent agent = controller.getAgent(deviceId);
118 - String tableDump = agent.dumpTable(tableName);
119 - return Bmv2TableDumpParser.parse(tableDump, context.configuration());
120 - } catch (Bmv2RuntimeException e) {
121 - log.warn("Unable to get table entries for {}: {}", deviceId, e.explain());
122 - return Collections.emptyList();
123 - }
124 - }
125 -
126 - @Override
127 public Bmv2FlowRuleWrapper lookupEntryReference(Bmv2TableEntryReference entryRef) { 102 public Bmv2FlowRuleWrapper lookupEntryReference(Bmv2TableEntryReference entryRef) {
128 checkNotNull(entryRef, "table entry reference cannot be null"); 103 checkNotNull(entryRef, "table entry reference cannot be null");
129 return flowRules.get(entryRef); 104 return flowRules.get(entryRef);
......
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.bmv2.ctl;
18 -
19 -import org.junit.Test;
20 -import org.onosproject.bmv2.api.context.Bmv2Configuration;
21 -import org.onosproject.bmv2.api.runtime.Bmv2ParsedTableEntry;
22 -
23 -import java.io.IOException;
24 -import java.net.URISyntaxException;
25 -import java.nio.charset.Charset;
26 -import java.nio.file.Files;
27 -import java.nio.file.Paths;
28 -import java.util.List;
29 -
30 -import static org.hamcrest.MatcherAssert.assertThat;
31 -import static org.hamcrest.Matchers.equalTo;
32 -
33 -public class Bmv2TableDumpParserTest {
34 -
35 - private Bmv2Configuration configuration = Bmv2DeviceContextServiceImpl.loadDefaultConfiguration();
36 -
37 - @Test
38 - public void testParse() throws Exception {
39 - String text = readFile();
40 - List<Bmv2ParsedTableEntry> result = Bmv2TableDumpParser.parse(text, configuration);
41 - assertThat(result.size(), equalTo(10));
42 - }
43 -
44 - private String readFile()
45 - throws IOException, URISyntaxException {
46 - byte[] encoded = Files.readAllBytes(Paths.get(this.getClass().getResource("/tabledump.txt").toURI()));
47 - return new String(encoded, Charset.defaultCharset());
48 - }
49 -}
1 -0: 0000 000000000000 000000000000 0806 &&& 0000000000000000000000000000ffff => send_to_cpu -
2 -1: 0000 000000000000 000000000000 0800 &&& 0000000000000000000000000000ffff => send_to_cpu -
3 -2: 0000 000000000000 000000000000 88cc &&& 0000000000000000000000000000ffff => send_to_cpu -
4 -3: 0000 000000000000 000000000000 8942 &&& 0000000000000000000000000000ffff => send_to_cpu -
5 -4: 0001 000400000001 000400000000 0000 &&& ffffffffffffffffffffffffffff0000 => set_egress_port - 2,
6 -5: 0002 000400000000 000400000001 0000 &&& ffffffffffffffffffffffffffff0000 => set_egress_port - 1,
7 -51539607552: 0001 0000 => set_egress_port - 1,
8 -51539607553: 0001 0002 => set_egress_port - 3,
9 -51539607554: 0001 0001 => set_egress_port - 2,
10 -51539607555: 0001 0003 => set_egress_port - 4,
...\ No newline at end of file ...\ No newline at end of file
...@@ -33,11 +33,11 @@ ...@@ -33,11 +33,11 @@
33 33
34 <properties> 34 <properties>
35 <!-- BMv2 Commit ID and Thrift version --> 35 <!-- BMv2 Commit ID and Thrift version -->
36 - <bmv2.commit>e55f9cdaee5e3d729f839e7ec6c322dd66c1a1a0</bmv2.commit> 36 + <bmv2.commit>024aa03e3b52f8d32c26774511e8e5b1dc11ec65</bmv2.commit>
37 <bmv2.thrift.version>0.9.3</bmv2.thrift.version> 37 <bmv2.thrift.version>0.9.3</bmv2.thrift.version>
38 <!-- Do not change below --> 38 <!-- Do not change below -->
39 <bmv2.baseurl> 39 <bmv2.baseurl>
40 - https://raw.githubusercontent.com/ccascone/behavioral-model/${bmv2.commit} 40 + https://raw.githubusercontent.com/opennetworkinglab/behavioral-model/${bmv2.commit}
41 </bmv2.baseurl> 41 </bmv2.baseurl>
42 <bmv2.thrift.srcdir>${project.basedir}/src/main/thrift</bmv2.thrift.srcdir> 42 <bmv2.thrift.srcdir>${project.basedir}/src/main/thrift</bmv2.thrift.srcdir>
43 <thrift.path>${project.build.directory}/thrift-compiler/</thrift.path> 43 <thrift.path>${project.build.directory}/thrift-compiler/</thrift.path>
......
...@@ -179,8 +179,7 @@ public class Bmv2PacketProvider extends AbstractProvider implements PacketProvid ...@@ -179,8 +179,7 @@ public class Bmv2PacketProvider extends AbstractProvider implements PacketProvid
179 private class InternalPacketListener implements Bmv2PacketListener { 179 private class InternalPacketListener implements Bmv2PacketListener {
180 180
181 @Override 181 @Override
182 - public void handlePacketIn(Bmv2Device device, int inputPort, long reason, int tableId, int contextId, 182 + public void handlePacketIn(Bmv2Device device, int inputPort, ImmutableByteSequence packet) {
183 - ImmutableByteSequence packet) {
184 Ethernet ethPkt = new Ethernet(); 183 Ethernet ethPkt = new Ethernet();
185 ethPkt.deserialize(packet.asArray(), 0, packet.size()); 184 ethPkt.deserialize(packet.asArray(), 0, packet.size());
186 185
......