Carmelo Cascone
Committed by Jonathan Hart

Added dump of table entry ids in bmv2 protocol

Change-Id: I54534cfb2c6188c922b36a2f8eb8e5c0851bc681
...@@ -19,6 +19,7 @@ package org.onosproject.bmv2.api.runtime; ...@@ -19,6 +19,7 @@ package org.onosproject.bmv2.api.runtime;
19 import org.onlab.util.ImmutableByteSequence; 19 import org.onlab.util.ImmutableByteSequence;
20 20
21 import java.util.Collection; 21 import java.util.Collection;
22 +import java.util.List;
22 23
23 /** 24 /**
24 * RPC client to control a BMv2 device. 25 * RPC client to control a BMv2 device.
...@@ -83,6 +84,24 @@ public interface Bmv2Client { ...@@ -83,6 +84,24 @@ public interface Bmv2Client {
83 String dumpTable(String tableName) throws Bmv2RuntimeException; 84 String dumpTable(String tableName) throws Bmv2RuntimeException;
84 85
85 /** 86 /**
87 + * Returns a list of ids for the entries installed in the given table.
88 + *
89 + * @param tableName string value of table name
90 + * @return a list of entry ids
91 + * @throws Bmv2RuntimeException if any error occurs
92 + */
93 + List<Long> getInstalledEntryIds(String tableName) throws Bmv2RuntimeException;
94 +
95 + /**
96 + * Removes all entries installed in the given table.
97 + *
98 + * @param tableName string value of table name
99 + * @return the number of entries removed
100 + * @throws Bmv2RuntimeException if any error occurs
101 + */
102 + int cleanupTable(String tableName) throws Bmv2RuntimeException;
103 +
104 + /**
86 * Requests the device to transmit a given byte sequence over the given port. 105 * Requests the device to transmit a given byte sequence over the given port.
87 * 106 *
88 * @param portNumber a port number 107 * @param portNumber a port number
......
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.collect.Lists;
20 +import org.apache.commons.lang3.tuple.Pair;
21 +
22 +import java.util.List;
23 +import java.util.regex.Matcher;
24 +import java.util.regex.Pattern;
25 +import java.util.stream.Collectors;
26 +
27 +import static com.google.common.base.Preconditions.checkNotNull;
28 +
29 +/**
30 + * String parser for the BMv2 table dump.
31 + */
32 +public class Bmv2TableDumpParser {
33 +
34 + /*
35 + Example of BMv2 table dump:
36 + 0: 0000 000000000000 000000000000 0806 &&& 0000000000000000000000000000ffff => send_to_cpu -
37 +
38 + For each entry, we want to match the id and all the rest.
39 + */
40 + private static final String ENTRY_PATTERN_STRING = "(\\d+):(.+)";
41 + private static final Pattern ENTRY_PATTERN = Pattern.compile(ENTRY_PATTERN_STRING);
42 +
43 + /**
44 + * Returns a list of entry Ids for the given table dump.
45 + *
46 + * @param tableDump a string value
47 + * @return a list of long values
48 + * @throws Bmv2TableDumpParserException if dump can't be parsed
49 + */
50 + public List<Long> getEntryIds(String tableDump) throws Bmv2TableDumpParserException {
51 + return parse(tableDump).stream().map(Pair::getKey).collect(Collectors.toList());
52 + }
53 +
54 + private List<Pair<Long, String>> parse(String tableDump) throws Bmv2TableDumpParserException {
55 + checkNotNull(tableDump, "tableDump cannot be null");
56 +
57 + List<Pair<Long, String>> results = Lists.newArrayList();
58 +
59 + // TODO: consider caching parser results for speed.
60 +
61 + Matcher matcher = ENTRY_PATTERN.matcher(tableDump);
62 +
63 + while (matcher.find()) {
64 + String entryString = matcher.group(1);
65 + if (entryString == null) {
66 + throw new Bmv2TableDumpParserException("Unable to parse entry for string: " + matcher.group());
67 + }
68 + Long entryId = -1L;
69 + try {
70 + entryId = Long.valueOf(entryString.trim());
71 + } catch (NumberFormatException e) {
72 + throw new Bmv2TableDumpParserException("Unable to parse entry id for string: " + matcher.group());
73 + }
74 + String allTheRest = matcher.group(2);
75 + if (allTheRest == null) {
76 + throw new Bmv2TableDumpParserException("Unable to parse entry for string: " + matcher.group());
77 + }
78 + results.add(Pair.of(entryId, allTheRest));
79 + }
80 +
81 + return results;
82 + }
83 +
84 + public class Bmv2TableDumpParserException extends Throwable {
85 + public Bmv2TableDumpParserException(String msg) {
86 + super(msg);
87 + }
88 + }
89 +}
...@@ -90,6 +90,9 @@ public final class Bmv2ThriftClient implements Bmv2Client { ...@@ -90,6 +90,9 @@ public final class Bmv2ThriftClient implements Bmv2Client {
90 .expireAfterAccess(CLIENT_CACHE_TIMEOUT, TimeUnit.SECONDS) 90 .expireAfterAccess(CLIENT_CACHE_TIMEOUT, TimeUnit.SECONDS)
91 .removalListener(new ClientRemovalListener()) 91 .removalListener(new ClientRemovalListener())
92 .build(new ClientLoader()); 92 .build(new ClientLoader());
93 +
94 + private static final Bmv2TableDumpParser TABLE_DUMP_PARSER = new Bmv2TableDumpParser();
95 +
93 private final Standard.Iface standardClient; 96 private final Standard.Iface standardClient;
94 private final SimpleSwitch.Iface simpleSwitchClient; 97 private final SimpleSwitch.Iface simpleSwitchClient;
95 private final TTransport transport; 98 private final TTransport transport;
...@@ -391,6 +394,44 @@ public final class Bmv2ThriftClient implements Bmv2Client { ...@@ -391,6 +394,44 @@ public final class Bmv2ThriftClient implements Bmv2Client {
391 } 394 }
392 395
393 @Override 396 @Override
397 + public List<Long> getInstalledEntryIds(String tableName) throws Bmv2RuntimeException {
398 +
399 + LOG.debug("Getting entry ids... > deviceId={}, tableName={}", deviceId, tableName);
400 +
401 + try {
402 + List<Long> entryIds = TABLE_DUMP_PARSER.getEntryIds(dumpTable(tableName));
403 + LOG.debug("Entry ids retrieved! > deviceId={}, tableName={}, entryIdsCount={}",
404 + deviceId, tableName, entryIds.size());
405 + return entryIds;
406 + } catch (Bmv2TableDumpParser.Bmv2TableDumpParserException e) {
407 + LOG.debug("Exception while retrieving entry ids: {} > deviceId={}, tableName={}",
408 + e, deviceId, tableName);
409 + throw new Bmv2RuntimeException(e.getMessage(), e);
410 + }
411 + }
412 +
413 + @Override
414 + public int cleanupTable(String tableName) throws Bmv2RuntimeException {
415 +
416 + LOG.debug("Starting table cleanup... > deviceId={}, tableName={}", deviceId, tableName);
417 +
418 + List<Long> entryIds = getInstalledEntryIds(tableName);
419 +
420 + int count = 0;
421 + for (Long entryId : entryIds) {
422 + try {
423 + standardClient.bm_mt_delete_entry(CONTEXT_ID, tableName, entryId);
424 + count++;
425 + } catch (TException e) {
426 + LOG.warn("Exception while deleting entry: {} > deviceId={}, tableName={}, entryId={}",
427 + e.toString(), deviceId, tableName, entryId);
428 + }
429 + }
430 +
431 + return count;
432 + }
433 +
434 + @Override
394 public void transmitPacket(int portNumber, ImmutableByteSequence packet) throws Bmv2RuntimeException { 435 public void transmitPacket(int portNumber, ImmutableByteSequence packet) throws Bmv2RuntimeException {
395 436
396 LOG.debug("Requesting packet transmission... > portNumber={}, packet={}", portNumber, packet); 437 LOG.debug("Requesting packet transmission... > portNumber={}, packet={}", portNumber, packet);
......
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.api.model;
18 +
19 +import org.junit.Test;
20 +import org.onosproject.bmv2.ctl.Bmv2TableDumpParser;
21 +
22 +import java.util.List;
23 +
24 +import static org.hamcrest.MatcherAssert.assertThat;
25 +import static org.hamcrest.core.Is.is;
26 +import static org.hamcrest.core.IsEqual.equalTo;
27 +
28 +public class Bmv2TableDumpParserTest {
29 +
30 + @Test
31 + public void testParse() throws Exception, Bmv2TableDumpParser.Bmv2TableDumpParserException {
32 +
33 + String text =
34 + "0: 0000 000000000000 000000000000 &&& 0000000000000000000000000000 => send_to_cpu -\n" +
35 + "1: 0000 000000000000 000000000000 &&& 0000000000000000000000000000 => send_to_cpu -\n" +
36 + "2: 0000 000000000000 000000000000 &&& 0000000000000000000000000000 => send_to_cpu -\n" +
37 + "3: 0000 000000000000 000000000000 &&& 0000000000000000000000000000 => send_to_cpu -";
38 +
39 + Bmv2TableDumpParser parser = new Bmv2TableDumpParser();
40 +
41 + List<Long> result = parser.getEntryIds(text);
42 +
43 + assertThat("invalid parsed values", result.get(0), is(equalTo(0L)));
44 + assertThat("invalid parsed values", result.get(1), is(equalTo(1L)));
45 + assertThat("invalid parsed values", result.get(2), is(equalTo(2L)));
46 + assertThat("invalid parsed values", result.get(3), is(equalTo(3L)));
47 + }
48 +}