changeset 1463:8f6c77f24b1a

csv_to_fd: add QoSFilterRule. style fixes Support derived type QoSFilterRule from RFC 7155 section 4.1.1 Minor code refactor. Expand comments, removing UTF-8 chars and encoding requirement.
author Luke Mewburn <luke@mewburn.net>
date Mon, 09 Mar 2020 22:28:04 +1100
parents b573eda8f4a2
children 1404de313b85
files contrib/tools/csv_to_fd
diffstat 1 files changed, 23 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/tools/csv_to_fd	Mon Mar 09 21:33:11 2020 +1100
+++ b/contrib/tools/csv_to_fd	Mon Mar 09 22:28:04 2020 +1100
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
 
 """
 Convert CSV files containing RADIUS or Diameter AVP tables
@@ -10,12 +9,16 @@
     Name, Code, Section, DataType, Must, May, ShouldNot, MustNot [, ...]
     - Name:
         AVP Name. String, validated as ALPHA *(ALPHA / DIGIT / "-")
+        per RFC 6733 section 3.2.
     - Code:
         AVP Code. Integer, 0..4294967295.
     - Section:
         Section in relevant standard. String.
     - DataType:
-        AVP Data Type. String, validated per Per RFC 6733 § 4.2 and § 4.3.
+        AVP Data Type. String, validated per basic and derived types in:
+            - RFC 6733 section 4.2
+            - RFC 6733 section 4.3
+            - RFC 7155 section 4.1
     - Must, May, ShouldNot, MustNot:
         Flags, possibly comma or space separated: M, V
 
@@ -55,6 +58,18 @@
     'encrypt',
 ]
 
+DERIVED_TO_BASE = {
+    'Address':          'OctetString',  # RFC 6733 section 4.3.1
+    'Time':             'OctetString',  # RFC 6733 section 4.3.1
+    'UTF8String':       'OctetString',  # RFC 6733 section 4.3.1
+    'DiameterIdentity': 'OctetString',  # RFC 6733 section 4.3.1
+    'DiameterURI':      'OctetString',  # RFC 6733 section 4.3.1
+    'Enumerated':       'Integer32',    # RFC 6733 section 4.3.1
+    'IPFilterRule':     'OctetString',  # RFC 6733 section 4.3.1
+    'QoSFilterRule':    'OctetString',  # RFC 7155 section 4.1.1
+}
+
+# See https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
 VENDOR_TO_NAME = {
     0:      '',
     193:    'Ericsson',
@@ -66,7 +81,7 @@
 class Avp(object):
     """Store an AVP row."""
 
-    # Regex to validate avp-name per RFC 6733 § 3.2,
+    # Regex to validate avp-name per RFC 6733 section 3.2,
     # with changes:
     # - Allow avp-name to start with numbers (for 3GPP)
     # - Allow '.' in avp-name, for existing dict_dcca_3gpp usage.
@@ -99,12 +114,10 @@
             raise ValueError('Invalid AVP name "{}"'.format(self.name))
         if (self.code < 0 or self.code > 4294967295):
             raise ValueError('Invalid AVP code {}'.format(self.code))
-        if self.datatype not in (
+        if (self.datatype not in (
                 'OctetString', 'Integer32', 'Integer64', 'Unsigned32',
-                'Unsigned64', 'Float32', 'Float64', 'Grouped',
-                'Address', 'Time', 'UTF8String', 'DiameterIdentity',
-                'DiameterURI', 'Enumerated', 'IPFilterRule',
-                ):
+                'Unsigned64', 'Float32', 'Float64', 'Grouped')
+                and self.datatype not in DERIVED_TO_BASE):
             raise ValueError('Invalid AVP data type "{}"'.format(
                 self.datatype))
 # TODO: validate must, may, shouldnot, mustnot
@@ -202,16 +215,6 @@
 
     COMMENT_WIDTH = 64
 
-    DERIVED_TO_BASE = {
-        'Address':          'OctetString',
-        'Time':             'OctetString',
-        'UTF8String':       'OctetString',
-        'DiameterIdentity': 'OctetString',
-        'DiameterURI':      'OctetString',
-        'Enumerated':       'Integer32',
-        'IPFilterRule':     'OctetString',
-    }
-
     def __init__(self):
         self.lines = []
 
@@ -235,8 +238,7 @@
             self.build_flags(avp.must)))
 # TODO: add trailing comma?
         self.add('\t\t\tAVP_TYPE_{}\t/* base type of data */'.format(
-            self.DERIVED_TO_BASE.get(
-                avp.datatype, avp.datatype).upper()))
+            DERIVED_TO_BASE.get(avp.datatype, avp.datatype).upper()))
         self.add('\t\t};')
         avp_type = 'NULL'
         if 'Enumerated' == avp.datatype:
@@ -251,7 +253,7 @@
 # XXX: add enumerated values
             self.add('\t\tCHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);')
             avp_type = "type"
-        elif avp.datatype in self.DERIVED_TO_BASE:
+        elif avp.datatype in DERIVED_TO_BASE:
             avp_type = '{}_type'.format(avp.datatype)
         self.add('\t\tCHECK_dict_new(DICT_AVP, &data, {}, NULL);'.format(
             avp_type))
"Welcome to our mercurial repository"