diff options
-rw-r--r-- | gobgp/global.go | 52 | ||||
-rw-r--r-- | packet/bgp.go | 26 |
2 files changed, 55 insertions, 23 deletions
diff --git a/gobgp/global.go b/gobgp/global.go index 9c272691..1ea62ddb 100644 --- a/gobgp/global.go +++ b/gobgp/global.go @@ -31,22 +31,16 @@ func showGlobalRib(args []string) error { return showNeighborRib(CMD_GLOBAL, bogusIp, args) } -func parseRD(args []string) (*api.RouteDistinguisher, error) { - t, err := strconv.Atoi(args[0]) - if err != nil { - return nil, err - } - typ := api.ROUTE_DISTINGUISHER_TYPE(t) - admin := args[1] - assigned, err := strconv.Atoi(args[2]) - if err != nil { - return nil, err +func getSerizliedRouteTarget(args []string) ([]byte, error) { + rts := make([]bgp.ExtendedCommunityInterface, 0, len(args)) + for _, elem := range args { + rt, err := bgp.ParseRouteTarget(elem) + if err != nil { + return nil, err + } + rts = append(rts, rt) } - return &api.RouteDistinguisher{ - Type: typ, - Admin: admin, - Assigned: uint32(assigned), - }, nil + return bgp.NewPathAttributeExtendedCommunities(rts).Serialize() } func modPath(modtype string, args []string) error { @@ -57,6 +51,7 @@ func modPath(modtype string, args []string) error { var nlri bgp.AddrPrefixInterface var nexthop string + var rts []string switch rf { case api.AF_IPV4_UC, api.AF_IPV6_UC: @@ -80,8 +75,8 @@ func modPath(modtype string, args []string) error { nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String()) } case api.AF_IPV4_VPN, api.AF_IPV6_VPN: - if len(args) < 3 || args[1] != "rd" { - return fmt.Errorf("usage: global rib %s <prefix> rd <rd> -a { vpn-ipv4 | vpn-ipv6 }", modtype) + if len(args) < 3 || args[1] != "rd" || args[3] != "rt" { + return fmt.Errorf("usage: global rib %s <prefix> rd <rd> rt <rt>... -a { vpn-ipv4 | vpn-ipv6 }", modtype) } ip, net, _ := net.ParseCIDR(args[0]) ones, _ := net.Mask.Size() @@ -91,6 +86,8 @@ func modPath(modtype string, args []string) error { return err } + rts = args[4:] + mpls := bgp.NewMPLSLabelStack() if rf == api.AF_IPV4_VPN { @@ -116,8 +113,8 @@ func modPath(modtype string, args []string) error { switch subtype { case "macadv": - if len(args) < 6 || args[4] != "rd" { - return fmt.Errorf("usage: global rib %s macadv <mac address> <ip address> <etag> <label> rd <rd> -a evpn", modtype) + if len(args) < 6 || args[4] != "rd" || args[6] != "rt" { + return fmt.Errorf("usage: global rib %s macadv <mac address> <ip address> <etag> <label> rd <rd> rt <rt>... -a evpn", modtype) } mac, err := net.ParseMAC(args[0]) if err != nil { @@ -147,6 +144,9 @@ func modPath(modtype string, args []string) error { if err != nil { return err } + + rts = args[7:] + macIpAdv := &bgp.EVPNMacIPAdvertisementRoute{ RD: rd, ESI: bgp.EthernetSegmentIdentifier{ @@ -161,8 +161,8 @@ func modPath(modtype string, args []string) error { } nlri = bgp.NewEVPNNLRI(bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT, 0, macIpAdv) case "multicast": - if len(args) < 5 || args[2] != "rd" { - return fmt.Errorf("usage : global rib %s multicast <ip address> <etag> rd <rd> -a evpn", modtype) + if len(args) < 5 || args[2] != "rd" || args[4] != "rt" { + return fmt.Errorf("usage : global rib %s multicast <ip address> <etag> rd <rd> rt <rt> -a evpn", modtype) } var ip net.IP @@ -188,6 +188,8 @@ func modPath(modtype string, args []string) error { return err } + rts = args[5:] + multicastEtag := &bgp.EVPNMulticastEthernetTagRoute{ RD: rd, IPAddressLength: uint8(iplen), @@ -227,6 +229,14 @@ func modPath(modtype string, args []string) error { origin, _ := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP).Serialize() arg.RawPattrs = append(arg.RawPattrs, origin) + if rts != nil && len(rts) > 0 { + extcomm, err := getSerizliedRouteTarget(rts) + if err != nil { + return err + } + arg.RawPattrs = append(arg.RawPattrs, extcomm) + } + stream, err := client.ModPath(context.Background()) if err != nil { return err diff --git a/packet/bgp.go b/packet/bgp.go index 35e70e72..31dde01f 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -860,7 +860,7 @@ func getRouteDistinguisher(data []byte) RouteDistinguisherInterface { return rd } -func parseRd(input string) ([]string, error) { +func parseRdAndRt(input string) ([]string, error) { exp := regexp.MustCompile("^((\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)|((\\d+)\\.)?(\\d+)):(\\d+)$") group := exp.FindSubmatch([]byte(input)) if len(group) != 10 { @@ -874,7 +874,7 @@ func parseRd(input string) ([]string, error) { } func ParseRouteDistinguisher(rd string) (RouteDistinguisherInterface, error) { - elems, err := parseRd(rd) + elems, err := parseRdAndRt(rd) if err != nil { return nil, err } @@ -3235,6 +3235,28 @@ func NewFourOctetAsSpecificExtended(as uint32, localAdmin uint16, isTransitive b } } +func ParseRouteTarget(rt string) (ExtendedCommunityInterface, error) { + elems, err := parseRdAndRt(rt) + if err != nil { + return nil, err + } + localAdmin, _ := strconv.Atoi(elems[9]) + ip := net.ParseIP(elems[1]) + isTransitive := true + switch { + case ip.To4() != nil: + return NewIPv4AddressSpecificExtended(elems[1], uint16(localAdmin), isTransitive), nil + case elems[6] == "" && elems[7] == "": + asn, _ := strconv.Atoi(elems[8]) + return NewTwoOctetAsSpecificExtended(uint16(asn), uint32(localAdmin), isTransitive), nil + default: + fst, _ := strconv.Atoi(elems[7]) + snd, _ := strconv.Atoi(elems[8]) + asn := fst<<16 | snd + return NewFourOctetAsSpecificExtended(uint32(asn), uint16(localAdmin), isTransitive), nil + } +} + type OpaqueExtendedValueInterface interface { Serialize() ([]byte, error) String() string |