Skip to content

Commit

Permalink
cli: Slash separated offset arg for FlowSpec Prefix
Browse files Browse the repository at this point in the history
Currently, "gobgp" command supports only;
  "<ipv6 prefix>/<len> <offset>"  # space separated
format to specify the prefix offset for the FlowSpec destination/source
rules, but the displayed format with "rib" command is;
  "<ipv6 prefix>/<len>/<offset>"  # slash separated
and the slash separated format is not allowed as command arguments.

This patch enables to specify the slash separated format for the
FlowSpec destination/source rules arguments and resolve unmatch of the
input/output formats.

Example:
$ gobgp global rib -a ipv6-flowspec add match destination 0:db8:1::1/64/16 then accept
$ gobgp global rib -a ipv6-flowspec
   Network                        Next Hop             AS_PATH              Age        Attrs
*> [destination: 0:db8:1::/64/16] fictitious                                00:00:00   [{Origin: ?}

Signed-off-by: IWASE Yusuke <[email protected]>
  • Loading branch information
iwaseyusuke authored and fujita committed Dec 30, 2017
1 parent 4aa2c43 commit 3f7e23f
Showing 1 changed file with 70 additions and 32 deletions.
102 changes: 70 additions & 32 deletions packet/bgp/bgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3099,35 +3099,40 @@ func flowSpecPrefixParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (F
// - IPv6 Prefix
// args := []string{"2001:db8:1::/64"}
// - IPv6 Prefix with offset
// args := []string{"2001:db8:1::/64", "16"}
// args := []string{"0:db8:1::/64/16"}
// args := []string{"0:db8:1::/64", "16"}
// - IPv6 Address
// args := []string{"2001:db8:1::1"}
// - IPv6 Address with offset
// args := []string{"0:db8:1::1", "16"}
afi, _ := RouteFamilyToAfiSafi(rf)
var prefix net.IP
var prefixLen int
_, nw, err := net.ParseCIDR(args[0])
if err != nil {
prefix = net.ParseIP(args[0])
if prefix == nil {
return nil, fmt.Errorf("invalid ip prefix: %s", args[0])
}
switch afi {
case AFI_IP:
prefixLen = net.IPv4len * 8
case AFI_IP6:
prefixLen = net.IPv6len * 8
}
} else {
prefix = nw.IP
prefixLen, _ = nw.Mask.Size()
}

switch afi {
case AFI_IP:
if prefix.To4() == nil {
return nil, fmt.Errorf("invalid ipv4 prefix: %s", args[0])
}
if len(args) > 1 {
return nil, fmt.Errorf("cannot specify offset for ipv4 prefix")
}
invalidIPv4PrefixError := fmt.Errorf("invalid ipv4 prefix: %s", args[0])
re := regexp.MustCompile("^([\\d.]+)(/(\\d{1,2}))?")
// re.FindStringSubmatch("192.168.0.0/24")
// >>> ["192.168.0.0/24" "192.168.0.0" "/24" "24"]
// re.FindStringSubmatch("192.168.0.1")
// >>> ["192.168.0.1" "192.168.0.1" "" ""]
m := re.FindStringSubmatch(args[0])
if len(m) < 4 {
return nil, invalidIPv4PrefixError
}
prefix := net.ParseIP(m[1])
if prefix.To4() == nil {
return nil, invalidIPv4PrefixError
}
var prefixLen uint64 = 32
if m[3] != "" {
var err error
prefixLen, err = strconv.ParseUint(m[3], 10, 8)
if err != nil || prefixLen > 32 {
return nil, invalidIPv4PrefixError
}
}
switch typ {
case FLOW_SPEC_TYPE_DST_PREFIX:
return NewFlowSpecDestinationPrefix(NewIPAddrPrefix(uint8(prefixLen), prefix.String())), nil
Expand All @@ -3136,22 +3141,55 @@ func flowSpecPrefixParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (F
}
return nil, fmt.Errorf("invalid traffic filtering rule type: %s", typ.String())
case AFI_IP6:
if len(args) > 2 {
return nil, fmt.Errorf("invalid arguments for ipv6 prefix: %q", args)
}
invalidIPv6PrefixError := fmt.Errorf("invalid ipv6 prefix: %s", args[0])
re := regexp.MustCompile("^([a-fA-F\\d:.]+)(/(\\d{1,3}))?(/(\\d{1,3}))?")
// re.FindStringSubmatch("2001:dB8::/64")
// >>> ["2001:dB8::/64" "2001:dB8::" "/64" "64" "" ""]
// re.FindStringSubmatch("2001:dB8::/64/8")
// >>> ["2001:dB8::/64/8" "2001:dB8::" "/64" "64" "/8" "8"]
// re.FindStringSubmatch("2001:dB8::1")
// >>> ["2001:dB8::1" "2001:dB8::1" "" "" "" ""]
m := re.FindStringSubmatch(args[0])
if len(m) < 4 {
return nil, invalidIPv6PrefixError
}
prefix := net.ParseIP(m[1])
if prefix.To16() == nil {
return nil, fmt.Errorf("invalid ipv6 prefix: %s", args[0])
return nil, invalidIPv6PrefixError
}
var prefixLen uint64 = 128
if m[3] != "" {
var err error
prefixLen, err = strconv.ParseUint(m[3], 10, 8)
if err != nil || prefixLen > 128 {
return nil, invalidIPv6PrefixError
}
}
var offset uint8
if len(args) > 1 {
o, err := strconv.Atoi(args[1])
if err != nil {
return nil, fmt.Errorf("invalid ipv6 prefix offset: %s", args[0])
var offset uint64
if len(args) == 1 && m[5] != "" {
var err error
offset, err = strconv.ParseUint(m[5], 10, 8)
if err != nil || offset > 128 {
return nil, fmt.Errorf("invalid ipv6 prefix offset: %s", m[5])
}
} else if len(args) == 2 {
if m[5] != "" {
return nil, fmt.Errorf("multiple ipv6 prefix offset arguments detected: %q", args)
}
var err error
offset, err = strconv.ParseUint(args[1], 10, 8)
if err != nil || offset > 128 {
return nil, fmt.Errorf("invalid ipv6 prefix offset: %s", args[1])
}
offset = uint8(o)
}
switch typ {
case FLOW_SPEC_TYPE_DST_PREFIX:
return NewFlowSpecDestinationPrefix6(NewIPv6AddrPrefix(uint8(prefixLen), prefix.String()), offset), nil
return NewFlowSpecDestinationPrefix6(NewIPv6AddrPrefix(uint8(prefixLen), prefix.String()), uint8(offset)), nil
case FLOW_SPEC_TYPE_SRC_PREFIX:
return NewFlowSpecSourcePrefix6(NewIPv6AddrPrefix(uint8(prefixLen), prefix.String()), offset), nil
return NewFlowSpecSourcePrefix6(NewIPv6AddrPrefix(uint8(prefixLen), prefix.String()), uint8(offset)), nil
}
return nil, fmt.Errorf("invalid traffic filtering rule type: %s", typ.String())
}
Expand Down

0 comments on commit 3f7e23f

Please sign in to comment.