From RFC 3986
IPv6address = 6( h16 ":" ) ls32
/ "::" 5( h16 ":" ) ls32
/ [ h16 ] "::" 4( h16 ":" ) ls32
/ [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
/ [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
/ [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
/ [ *4( h16 ":" ) h16 ] "::" ls32
/ [ *5( h16 ":" ) h16 ] "::" h16
/ [ *6( h16 ":" ) h16 ] "::"
h16 = 1*4HEXDIG
ls32 = ( h16 ":" h16 ) / IPv4address
IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
dec-octet = DIGIT ; 0-9
/ %x31-39 DIGIT ; 10-99
/ "1" 2DIGIT ; 100-199
/ "2" %x30-34 DIGIT ; 200-249
/ "25" %x30-35 ; 250-255
This is likely to be incorrect but should still but useful.
NL = CR / CRLF MASK = MASK4 / MASK6 MASK4 = 1*DIGIT ; max 32 MASK6 = 1*DIGIT ; max 128 ASN = ASN2 / ASN4 ASN2 = 1*DIGIT ; max 2^16 ASN4 = 1*DIGIT ; max 2^32 number = 1*DIGIT ; should split 16 and 32 bits number ...
configuration = 1*neigbor 1*NL
neighbor = 'neighbor' IP '{' NL neighbor_body '}' [ NL ]
IP = IPv4address / IPv6address
neighbor_body = [description]
neighbor_body =/ router-id
neighbor_body =/ local-address
neighbor_body =/ local-as
neighbor_body =/ peer-as
neighbor_body =/ [ graceful-restart ]
neighbor_body =/ [ hold-time ]
neighbor_body =/ static / flow / static flow / flow static
router-id = 'router-id' IPv4address ';' NL
local-address = 'local-address' IP ';' NL
local-as = 'local-as' ASN ';' NL
peer-as = 'peer-as' ASN ';' NL
graceful-restart = 'graceful-restart' [ number ] ';' NL
hold-time = 'hold-time' [ number ] ';' NL
static = 'static' '{' NL 1*static-route '}' NL
flow = 'flow' '{' NL 1*flow-route '}' NL
static-route = 1*single-static | 1*multi-static
single-static = 'route' ((IP6Address '/' MASK6)/(IP4Address '/' MASK4)) next-hop [local-preference] [med] [community] [as-path] ';'
multi-static = 'route' [1*ALPHA] '{' NL static-group '}' NL
static-group = next-hop [ local-preference ';' NL ] [ med ';' NL ] [ community ';' NL] [ as-path ';' ]
next-hop = 'next-hop' IP
local-preference = 'local-preference' number
med = 'med' number
community = 'community' communities
communities = community_value / '[' 1*community_value ']'
community_value = number
community_value =/ ('0x'/'0X') 1*HEXDIG
community_value =/ ASN2 ':' ASN2
as-path = '[' 1*ASN ']'
flow-route = 'route' [*ALPHA] '{' NL 'match' '{' NL flow-conditions '}' NL 'then' '{' flow-action '}' NL '}' NL
flow-conditions = *1source *1destination *1port *1dport *1sport *1protocol *1packet-length *1fragment *1icmp-type *1icmp-code *1tcp-flags *1dscp
source = 'source' IPv4Address '/' MASK4 ';' NL
destination = 'destination' IPv4Address '/' MASK4 ';' NL
port = 'port' digit-range ';' NL
dport = 'destination-port' digit-range ';' NL
sport = 'source-port' digit-range ';' NL
procol = 'protocol' supported-proto / ('[' 1* supported-proto ']') ';' NL
supported-proto = number / 'tcp' / 'udp' /
packet-length = 'packet-length' digit-range ';' NL
fragment = 'fragment' valid-fragment / ('[' 1* valid-fragment ']') ';' NL
valid-fragment = 'first-fragment' / 'last-fragment' / ...
icmp-type = 'icmp-type' types / ('[' 1* types ']') ';' NL
icmp-code = 'icmp-code' codes / ('[' 1* codes ']') ';' NL
types = 'unreachable' / 'echo-request' / 'echo-reply' / ...
codes = 'host-unreachable' / 'network-unreachable' / ...
tcp-flags = 'tcp-flags' flags / ('[' 1* flags ']') ';' NL
flags = 'urgent' / 'rst' / ...
dscp = 'dscp' digit-range ';' NL
digit-range = digit-maths / digit-list
How do you express that compare and number should not be space separated ?
digit-maths = digit-math [ '&' digit-maths ] digit-math = compare number compare = '>' / '<' / '=' / '>=' / '<=' digit-list = '[' 1*number ']' flow-action = 'rate-limit' number ';' NL flow-action = 'discard' ';' NL flow-action = 'redirect' ((IP ':' number) / (ASN2 ':' ASN2)) ';' NL