func ParseEvpnMacAdvArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { if len(args) < 4 { return nil, nil, fmt.Errorf("lack of number of args needs 4 but %d", len(args)) } var nlri bgp.AddrPrefixInterface var ip net.IP iplen := 0 mac, err := net.ParseMAC(args[0]) if err != nil { return nil, nil, fmt.Errorf("invalid mac: %s", args[0]) } if args[1] != "0.0.0.0" && args[1] != "::" { ip = net.ParseIP(args[1]) if ip == nil { return nil, nil, fmt.Errorf("invalid ip prefix: %s", args[1]) } iplen = net.IPv4len * 8 if ip.To4() == nil { iplen = net.IPv6len * 8 } } eTag, err := strconv.Atoi(args[2]) if err != nil { return nil, nil, fmt.Errorf("invalid eTag: %s. err: %s", args[2], err) } label, err := strconv.Atoi(args[3]) if err != nil { return nil, nil, fmt.Errorf("invalid label: %s. err: %s", args[3], err) } var rd bgp.RouteDistinguisherInterface if args[4] == "rd" && len(args) > 5 { rd, err = bgp.ParseRouteDistinguisher(args[5]) if err != nil { return nil, nil, err } } macIpAdv := &bgp.EVPNMacIPAdvertisementRoute{ RD: rd, ESI: bgp.EthernetSegmentIdentifier{ Type: bgp.ESI_ARBITRARY, }, MacAddressLength: 48, MacAddress: mac, IPAddressLength: uint8(iplen), IPAddress: ip, Labels: []uint32{uint32(label)}, ETag: uint32(eTag), } nlri = bgp.NewEVPNNLRI(bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT, 0, macIpAdv) extcomms := args[6:] return nlri, extcomms, nil }
func ParseEVPNIPPrefixArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { if len(args) < 6 { return nil, nil, fmt.Errorf("lack of number of args needs 6 at least but got %d", len(args)) } m := extractReserved(args, []string{"gw", "rd", "rt", "encap", "etag", "label"}) if len(m[""]) < 1 { return nil, nil, fmt.Errorf("specify prefix") } ip, n, err := net.ParseCIDR(m[""][0]) if err != nil { return nil, nil, err } ones, _ := n.Mask.Size() var gw net.IP if len(m["gw"]) > 0 { gw = net.ParseIP(m["gw"][0]) } if len(m["rd"]) < 1 { return nil, nil, fmt.Errorf("specify RD") } rd, err := bgp.ParseRouteDistinguisher(m["rd"][0]) if err != nil { return nil, nil, err } var etag uint32 if len(m["etag"]) > 0 { e, err := strconv.Atoi(m["etag"][0]) if err != nil { return nil, nil, err } etag = uint32(e) } var label uint32 if len(m["label"]) > 0 { e, err := strconv.Atoi(m["label"][0]) if err != nil { return nil, nil, err } label = uint32(e) } r := &bgp.EVPNIPPrefixRoute{ RD: rd, ETag: etag, IPPrefixLength: uint8(ones), IPPrefix: ip, GWIPAddress: gw, Label: label, } return bgp.NewEVPNNLRI(bgp.EVPN_IP_PREFIX, 0, r), nil, nil }
func modVrf(typ string, args []string) error { var err error switch typ { case CMD_ADD: a := extractReserved(args, []string{"rd", "rt", "id"}) if len(a[""]) != 1 || len(a["rd"]) != 1 || len(a["rt"]) < 2 || len(a["id"]) > 1 { return fmt.Errorf("Usage: gobgp vrf add <vrf name> [ id <id> ] rd <rd> rt { import | export | both } <rt>...") } name := a[""][0] rd, err := bgp.ParseRouteDistinguisher(a["rd"][0]) if err != nil { return err } cur := "" importRt := make([]bgp.ExtendedCommunityInterface, 0) exportRt := make([]bgp.ExtendedCommunityInterface, 0) for _, elem := range a["rt"] { if elem == "import" || elem == "export" || elem == "both" { cur = elem continue } rt, err := bgp.ParseRouteTarget(elem) if err != nil { return err } switch cur { case "import": importRt = append(importRt, rt) case "export": exportRt = append(exportRt, rt) case "both": importRt = append(importRt, rt) exportRt = append(exportRt, rt) default: return fmt.Errorf("Usage: gobgp vrf add <vrf name> rd <rd> rt { import | export | both } <rt>...") } } vrfId := 0 if len(a["id"]) > 0 { vrfId, err = strconv.Atoi(a["id"][0]) if err != nil { return err } } err = client.AddVRF(name, vrfId, rd, importRt, exportRt) case CMD_DEL: if len(args) != 1 { return fmt.Errorf("Usage: gobgp vrf del <vrf name>") } err = client.DeleteVRF(args[0]) } return err }
func extractRouteDistinguisher(args []string) ([]string, bgp.RouteDistinguisherInterface, error) { for idx, arg := range args { if arg == "rd" { if len(args) < (idx + 1) { return nil, nil, fmt.Errorf("invalid rd format") } rd, err := bgp.ParseRouteDistinguisher(args[idx+1]) if err != nil { return nil, nil, err } return append(args[:idx], args[idx+2:]...), rd, nil } } return args, nil, nil }
func ParseEvpnMulticastArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { if len(args) < 2 { return nil, nil, fmt.Errorf("lack of number of args needs 2 but %d", len(args)) } var nlri bgp.AddrPrefixInterface var ip net.IP iplen := 0 if args[0] != "0.0.0.0" && args[0] != "::" { ip = net.ParseIP(args[0]) if ip == nil { return nil, nil, fmt.Errorf("invalid ip prefix: %s", args[0]) } iplen = net.IPv4len * 8 if ip.To4() == nil { iplen = net.IPv6len * 8 } } eTag, err := strconv.Atoi(args[1]) if err != nil { return nil, nil, fmt.Errorf("invalid eTag: %s. err: %s", args[1], err) } var rd bgp.RouteDistinguisherInterface if args[2] == "rd" && len(args) > 3 { rd, err = bgp.ParseRouteDistinguisher(args[3]) if err != nil { return nil, nil, err } } multicastEtag := &bgp.EVPNMulticastEthernetTagRoute{ RD: rd, IPAddressLength: uint8(iplen), IPAddress: ip, ETag: uint32(eTag), } extcomms := args[4:] nlri = bgp.NewEVPNNLRI(bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG, 0, multicastEtag) return nlri, extcomms, nil }
func modVrf(typ string, args []string) error { var err error switch typ { case CMD_ADD: if len(args) < 6 || args[1] != "rd" || args[3] != "rt" { return fmt.Errorf("Usage: gobgp vrf add <vrf name> rd <rd> rt { import | export | both } <rt>...") } name := args[0] rd, err := bgp.ParseRouteDistinguisher(args[2]) if err != nil { return err } cur := "" importRt := make([][]byte, 0) exportRt := make([][]byte, 0) for _, elem := range args[4:] { if elem == "import" || elem == "export" || elem == "both" { cur = elem continue } rt, err := bgp.ParseRouteTarget(elem) if err != nil { return err } buf, err := rt.Serialize() if err != nil { return err } switch cur { case "import": importRt = append(importRt, buf) case "export": exportRt = append(exportRt, buf) case "both": importRt = append(importRt, buf) exportRt = append(exportRt, buf) default: return fmt.Errorf("Usage: gobgp vrf add <vrf name> rd <rd> rt { import | export | both } <rt>...") } } buf, _ := rd.Serialize() arg := &api.AddVrfRequest{ Vrf: &api.Vrf{ Name: name, Rd: buf, ImportRt: importRt, ExportRt: exportRt, }, } _, err = client.AddVrf(context.Background(), arg) case CMD_DEL: if len(args) != 1 { return fmt.Errorf("Usage: gobgp vrf del <vrf name>") } arg := &api.DeleteVrfRequest{ Vrf: &api.Vrf{ Name: args[0], }, } _, err = client.DeleteVrf(context.Background(), arg) } return err }
func ParsePath(rf bgp.RouteFamily, args []string) (*api.Path, error) { var nlri bgp.AddrPrefixInterface var extcomms []string var err error attrs := table.PathAttrs(make([]bgp.PathAttributeInterface, 0, 1)) path := &api.Path{ Pattrs: make([][]byte, 0), } fns := []func([]string) ([]string, bgp.PathAttributeInterface, error){ extractOrigin, extractMed, extractLocalPref, extractCommunity, extractAigp, } for _, fn := range fns { var a bgp.PathAttributeInterface args, a, err = fn(args) if err != nil { return nil, err } if a != nil { attrs = append(attrs, a) } } args, nexthop, err := extractNexthop(rf, args) if err != nil { return nil, err } switch rf { case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: if len(args) < 1 { return nil, fmt.Errorf("invalid format") } ip, net, err := net.ParseCIDR(args[0]) if err != nil { return nil, err } ones, _ := net.Mask.Size() if rf == bgp.RF_IPv4_UC { if ip.To4() == nil { return nil, fmt.Errorf("invalid ipv4 prefix") } nlri = bgp.NewIPAddrPrefix(uint8(ones), ip.String()) } else { if ip.To16() == nil { return nil, fmt.Errorf("invalid ipv6 prefix") } nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String()) } extcomms = args[1:] case bgp.RF_IPv4_VPN, bgp.RF_IPv6_VPN: if len(args) < 3 || args[1] != "rd" { return nil, fmt.Errorf("invalid format") } ip, net, _ := net.ParseCIDR(args[0]) ones, _ := net.Mask.Size() rd, err := bgp.ParseRouteDistinguisher(args[2]) if err != nil { return nil, err } extcomms = args[3:] mpls := bgp.NewMPLSLabelStack() if rf == bgp.RF_IPv4_VPN { if ip.To4() == nil { return nil, fmt.Errorf("invalid ipv4 prefix") } nlri = bgp.NewLabeledVPNIPAddrPrefix(uint8(ones), ip.String(), *mpls, rd) } else { if ip.To16() == nil { return nil, fmt.Errorf("invalid ipv6 prefix") } nlri = bgp.NewLabeledVPNIPv6AddrPrefix(uint8(ones), ip.String(), *mpls, rd) } case bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS: if len(args) < 2 { return nil, fmt.Errorf("invalid format") } ip, net, _ := net.ParseCIDR(args[0]) ones, _ := net.Mask.Size() mpls, err := bgp.ParseMPLSLabelStack(args[1]) if err != nil { return nil, err } extcomms = args[2:] if rf == bgp.RF_IPv4_MPLS { if ip.To4() == nil { return nil, fmt.Errorf("invalid ipv4 prefix") } nlri = bgp.NewLabeledIPAddrPrefix(uint8(ones), ip.String(), *mpls) } else { if ip.To4() != nil { return nil, fmt.Errorf("invalid ipv6 prefix") } nlri = bgp.NewLabeledIPv6AddrPrefix(uint8(ones), ip.String(), *mpls) } case bgp.RF_EVPN: nlri, extcomms, err = ParseEvpnArgs(args) case bgp.RF_FS_IPv4_UC, bgp.RF_FS_IPv6_UC, bgp.RF_FS_L2_VPN: nlri, extcomms, err = ParseFlowSpecArgs(rf, args) case bgp.RF_OPAQUE: m := extractReserved(args, []string{"key", "value"}) if len(m["key"]) != 1 || len(m["value"]) != 1 { return nil, fmt.Errorf("invalid key-value format") } nlri = bgp.NewOpaqueNLRI([]byte(m["key"][0])) attrs = append(attrs, bgp.NewPathAttributeOpaqueValue([]byte(m["value"][0]))) default: return nil, fmt.Errorf("Unsupported route family: %s", rf) } if err != nil { return nil, err } if rf == bgp.RF_IPv4_UC { path.Nlri, _ = nlri.Serialize() attrs = append(attrs, bgp.NewPathAttributeNextHop(nexthop)) } else { mpreach := bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri}) attrs = append(attrs, mpreach) } if extcomms != nil && len(extcomms) > 0 { extcomms, err := ParseExtendedCommunities(strings.Join(extcomms, " ")) if err != nil { return nil, err } p := bgp.NewPathAttributeExtendedCommunities(extcomms) attrs = append(attrs, p) } sort.Sort(attrs) for _, attr := range attrs { buf, err := attr.Serialize() if err != nil { return nil, err } path.Pattrs = append(path.Pattrs, buf) } return path, nil }
func ParsePath(rf bgp.RouteFamily, args []string) (*table.Path, error) { var nlri bgp.AddrPrefixInterface var rd bgp.RouteDistinguisherInterface var extcomms []string var err error attrs := table.PathAttrs(make([]bgp.PathAttributeInterface, 0, 1)) fns := []func([]string) ([]string, bgp.PathAttributeInterface, error){ extractOrigin, extractMed, extractLocalPref, extractCommunity, extractAigp, extractAggregator, extractLargeCommunity, } for _, fn := range fns { var a bgp.PathAttributeInterface args, a, err = fn(args) if err != nil { return nil, err } if a != nil { attrs = append(attrs, a) } } args, nexthop, err := extractNexthop(rf, args) if err != nil { return nil, err } switch rf { case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: if len(args) < 1 { return nil, fmt.Errorf("invalid format") } ip, net, err := net.ParseCIDR(args[0]) if err != nil { return nil, err } ones, _ := net.Mask.Size() if rf == bgp.RF_IPv4_UC { if ip.To4() == nil { return nil, fmt.Errorf("invalid ipv4 prefix") } nlri = bgp.NewIPAddrPrefix(uint8(ones), ip.String()) } else { if ip.To16() == nil { return nil, fmt.Errorf("invalid ipv6 prefix") } nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String()) } extcomms = args[1:] case bgp.RF_IPv4_VPN, bgp.RF_IPv6_VPN: if len(args) < 5 || args[1] != "label" || args[3] != "rd" { return nil, fmt.Errorf("invalid format") } ip, net, _ := net.ParseCIDR(args[0]) ones, _ := net.Mask.Size() label := 0 if label, err = strconv.Atoi(args[2]); err != nil { return nil, fmt.Errorf("invalid format") } mpls := bgp.NewMPLSLabelStack(uint32(label)) rd, err = bgp.ParseRouteDistinguisher(args[4]) if err != nil { return nil, err } extcomms = args[5:] if rf == bgp.RF_IPv4_VPN { if ip.To4() == nil { return nil, fmt.Errorf("invalid ipv4 prefix") } nlri = bgp.NewLabeledVPNIPAddrPrefix(uint8(ones), ip.String(), *mpls, rd) } else { if ip.To16() == nil { return nil, fmt.Errorf("invalid ipv6 prefix") } nlri = bgp.NewLabeledVPNIPv6AddrPrefix(uint8(ones), ip.String(), *mpls, rd) } case bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS: if len(args) < 2 { return nil, fmt.Errorf("invalid format") } ip, net, _ := net.ParseCIDR(args[0]) ones, _ := net.Mask.Size() mpls, err := bgp.ParseMPLSLabelStack(args[1]) if err != nil { return nil, err } extcomms = args[2:] if rf == bgp.RF_IPv4_MPLS { if ip.To4() == nil { return nil, fmt.Errorf("invalid ipv4 prefix") } nlri = bgp.NewLabeledIPAddrPrefix(uint8(ones), ip.String(), *mpls) } else { if ip.To4() != nil { return nil, fmt.Errorf("invalid ipv6 prefix") } nlri = bgp.NewLabeledIPv6AddrPrefix(uint8(ones), ip.String(), *mpls) } case bgp.RF_EVPN: nlri, extcomms, err = ParseEvpnArgs(args) case bgp.RF_FS_IPv4_VPN, bgp.RF_FS_IPv6_VPN, bgp.RF_FS_L2_VPN: args, rd, err = extractRouteDistinguisher(args) if err != nil { return nil, err } fallthrough case bgp.RF_FS_IPv4_UC, bgp.RF_FS_IPv6_UC: nlri, extcomms, err = ParseFlowSpecArgs(rf, args, rd) case bgp.RF_OPAQUE: m := extractReserved(args, []string{"key", "value"}) if len(m["key"]) != 1 { return nil, fmt.Errorf("opaque nlri key missing") } if len(m["value"]) > 0 { nlri = bgp.NewOpaqueNLRI([]byte(m["key"][0]), []byte(m["value"][0])) } else { nlri = bgp.NewOpaqueNLRI([]byte(m["key"][0]), nil) } default: return nil, fmt.Errorf("Unsupported route family: %s", rf) } if err != nil { return nil, err } if rf == bgp.RF_IPv4_UC { attrs = append(attrs, bgp.NewPathAttributeNextHop(nexthop)) } else { mpreach := bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri}) attrs = append(attrs, mpreach) } if extcomms != nil && len(extcomms) > 0 { extcomms, err := ParseExtendedCommunities(strings.Join(extcomms, " ")) if err != nil { return nil, err } p := bgp.NewPathAttributeExtendedCommunities(extcomms) attrs = append(attrs, p) } sort.Sort(attrs) return table.NewPath(nil, nlri, false, attrs, time.Now(), false), nil }