aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOle Troan <ot@cisco.com>2019-04-23 17:11:01 +0200
committerAndrew Yourtchenko <ayourtch@gmail.com>2019-04-29 12:07:02 +0000
commit9ac113815511f3ce37b56a1331d6491fc36f7db5 (patch)
tree574f66ce291ee75de2545a051be77a11bbaa43e2
parentde146e5d5f7e919b423feeff3159c4ecd564c353 (diff)
API: Add support for limits to language.
string name [limit = 64]; Meta-data to do argument validation. Change-Id: I1f3e0f09b2d5285224399413d25206f77bd3f4b1 Signed-off-by: Ole Troan <ot@cisco.com>
-rwxr-xr-xsrc/tools/vppapigen/vppapigen.py16
-rw-r--r--src/tools/vppapigen/vppapigen_json.py5
-rwxr-xr-xsrc/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py17
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_serializer.py30
-rw-r--r--src/vpp-api/vapi/vapi_json_parser.py9
-rw-r--r--src/vpp/api/vpe.api8
6 files changed, 65 insertions, 20 deletions
diff --git a/src/tools/vppapigen/vppapigen.py b/src/tools/vppapigen/vppapigen.py
index c2f221b9e79..ae2b0b1ba40 100755
--- a/src/tools/vppapigen/vppapigen.py
+++ b/src/tools/vppapigen/vppapigen.py
@@ -298,10 +298,11 @@ class Array():
class Field():
- def __init__(self, fieldtype, name):
+ def __init__(self, fieldtype, name, limit=None):
self.type = 'Field'
self.fieldtype = fieldtype
self.fieldname = name
+ self.limit = limit
def __repr__(self):
return str([self.fieldtype, self.fieldname])
@@ -504,7 +505,7 @@ class VPPAPIParser(object):
def p_enum_statements(self, p):
'''enum_statements : enum_statement
- | enum_statements enum_statement'''
+ | enum_statements enum_statement'''
if len(p) == 2:
p[0] = [p[1]]
else:
@@ -519,11 +520,16 @@ class VPPAPIParser(object):
p[0] = p[1]
def p_declaration(self, p):
- '''declaration : type_specifier ID ';' '''
- if len(p) != 4:
+ '''declaration : type_specifier ID ';'
+ | type_specifier ID '[' ID '=' assignee ']' ';' '''
+ if len(p) == 9:
+ p[0] = Field(p[1], p[2], {p[4]: p[6]})
+ elif len(p) == 4:
+ p[0] = Field(p[1], p[2])
+ else:
self._parse_error('ERROR')
self.fields.append(p[2])
- p[0] = Field(p[1], p[2])
+
def p_declaration_array(self, p):
'''declaration : type_specifier ID '[' NUM ']' ';'
diff --git a/src/tools/vppapigen/vppapigen_json.py b/src/tools/vppapigen/vppapigen_json.py
index c563a089949..94a9e19577e 100644
--- a/src/tools/vppapigen/vppapigen_json.py
+++ b/src/tools/vppapigen/vppapigen_json.py
@@ -33,7 +33,10 @@ def walk_defs(s):
d.append(t.name)
for b in t.block:
if b.type == 'Field':
- d.append([b.fieldtype, b.fieldname])
+ if b.limit:
+ d.append([b.fieldtype, b.fieldname, b.limit])
+ else:
+ d.append([b.fieldtype, b.fieldname])
elif b.type == 'Array':
if b.lengthfield:
d.append([b.fieldtype, b.fieldname, b.length, b.lengthfield])
diff --git a/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py b/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py
index 4fbda2a01af..ec7334712ab 100755
--- a/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py
+++ b/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py
@@ -3,12 +3,27 @@
import unittest
from vpp_papi.vpp_serializer import VPPType, VPPEnumType
from vpp_papi.vpp_serializer import VPPUnionType, VPPMessage
-from vpp_papi.vpp_serializer import VPPTypeAlias
+from vpp_papi.vpp_serializer import VPPTypeAlias, VPPSerializerValueError
from socket import inet_pton, AF_INET, AF_INET6
import logging
import sys
from ipaddress import *
+class TestLimits(unittest.TestCase):
+ def test_limit(self):
+ limited_type = VPPType('limited_type_t',
+ [['string', 'name', {'limit': 16}]])
+ unlimited_type = VPPType('limited_type_t',
+ [['string', 'name']])
+
+
+ b = limited_type.pack({'name':'foobar'})
+ self.assertEqual(len(b), 10)
+ b = unlimited_type.pack({'name':'foobar'})
+ self.assertEqual(len(b), 10)
+
+ with self.assertRaises(VPPSerializerValueError):
+ b = limited_type.pack({'name':'foobar'*3})
class TestAddType(unittest.TestCase):
diff --git a/src/vpp-api/python/vpp_papi/vpp_serializer.py b/src/vpp-api/python/vpp_papi/vpp_serializer.py
index bd5f050bba9..d1093318ed0 100644
--- a/src/vpp-api/python/vpp_papi/vpp_serializer.py
+++ b/src/vpp-api/python/vpp_papi/vpp_serializer.py
@@ -96,14 +96,20 @@ class BaseTypes(object):
class String(object):
- def __init__(self):
+ def __init__(self, options):
self.name = 'string'
self.size = 1
self.length_field_packer = BaseTypes('u32')
+ self.limit = options['limit'] if 'limit' in options else None
def pack(self, list, kwargs=None):
if not list:
return self.length_field_packer.pack(0) + b""
+ if self.limit and len(list) > self.limit:
+ raise VPPSerializerValueError(
+ "Invalid argument length for: {}, {} maximum {}".
+ format(list, len(list), self.limit))
+
return self.length_field_packer.pack(len(list)) + list.encode('utf8')
def unpack(self, data, offset=0, result=None, ntc=False):
@@ -120,7 +126,7 @@ class String(object):
types = {'u8': BaseTypes('u8'), 'u16': BaseTypes('u16'),
'u32': BaseTypes('u32'), 'i32': BaseTypes('i32'),
'u64': BaseTypes('u64'), 'f64': BaseTypes('f64'),
- 'bool': BaseTypes('bool'), 'string': String()}
+ 'bool': BaseTypes('bool'), 'string': String}
def vpp_get_type(name):
@@ -416,7 +422,15 @@ class VPPType(object):
logger.debug('Unknown type {}'.format(f_type))
raise VPPSerializerValueError(
'Unknown message type {}'.format(f_type))
- if len(f) == 3: # list
+
+ l = len(f)
+ options = [x for x in f if type(x) is dict]
+ if len(options):
+ self.options = options[0]
+ l -= 1
+ else:
+ self.options = {}
+ if l == 3: # list
list_elements = f[2]
if list_elements == 0:
p = VLAList_legacy(f_name, f_type)
@@ -429,13 +443,17 @@ class VPPType(object):
p = FixedList(f_name, f_type, list_elements)
self.packers.append(p)
size += p.size
- elif len(f) == 4: # Variable length list
+ elif l == 4: # Variable length list
length_index = self.fields.index(f[3])
p = VLAList(f_name, f_type, f[3], length_index)
self.packers.append(p)
else:
- self.packers.append(types[f_type])
- size += types[f_type].size
+ if f_type == 'string':
+ p = types[f_type](self.options)
+ else:
+ p = types[f_type]
+ self.packers.append(p)
+ size += p.size
self.size = size
self.tuple = collections.namedtuple(name, self.fields, rename=True)
diff --git a/src/vpp-api/vapi/vapi_json_parser.py b/src/vpp-api/vapi/vapi_json_parser.py
index fda3f75d9c1..fbeb1887ac2 100644
--- a/src/vpp-api/vapi/vapi_json_parser.py
+++ b/src/vpp-api/vapi/vapi_json_parser.py
@@ -167,13 +167,16 @@ class Message(object):
else:
field_type = json_parser.lookup_type_like_id(field[0])
logger.debug("Parsing message field `%s'" % field)
- if len(field) == 2:
+ l = len(field)
+ if any(type(n) is dict for n in field):
+ l -= 1
+ if l == 2:
if self.header is not None and\
self.header.has_field(field[1]):
continue
p = field_class(field_name=field[1],
field_type=field_type)
- elif len(field) == 3:
+ elif l == 3:
if field[2] == 0:
raise ParseError(
"While parsing message `%s': variable length "
@@ -184,7 +187,7 @@ class Message(object):
field_name=field[1],
field_type=field_type,
array_len=field[2])
- elif len(field) == 4:
+ elif l == 4:
nelem_field = None
for f in fields:
if f.name == field[3]:
diff --git a/src/vpp/api/vpe.api b/src/vpp/api/vpe.api
index a2a677926e1..94732bbc236 100644
--- a/src/vpp/api/vpe.api
+++ b/src/vpp/api/vpe.api
@@ -183,10 +183,10 @@ define show_version_reply
{
u32 context;
i32 retval;
- string program;
- string version;
- string build_date;
- string build_directory;
+ string program [limit = 32];
+ string version [limit = 32];
+ string build_date [limit = 32];
+ string build_directory [limit = 256];
};