func (manager *TableManager) AddVrf(name string, id uint32, rd bgp.RouteDistinguisherInterface, importRt, exportRt []bgp.ExtendedCommunityInterface, info *PeerInfo) ([]*Path, error) { if _, ok := manager.Vrfs[name]; ok { return nil, fmt.Errorf("vrf %s already exists", name) } log.WithFields(log.Fields{ "Topic": "Vrf", "Key": name, "Rd": rd, "ImportRt": importRt, "ExportRt": exportRt, }).Debugf("add vrf") manager.Vrfs[name] = &Vrf{ Name: name, Id: id, Rd: rd, ImportRt: importRt, ExportRt: exportRt, } msgs := make([]*Path, 0, len(importRt)) nexthop := "0.0.0.0" for _, target := range importRt { nlri := bgp.NewRouteTargetMembershipNLRI(info.AS, target) pattr := make([]bgp.PathAttributeInterface, 0, 2) pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP)) pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri})) msgs = append(msgs, NewPath(info, nlri, false, pattr, time.Now(), false)) } return msgs, nil }
func createPathFromIPRouteMessage(m *zebra.Message) *table.Path { header := m.Header body := m.Body.(*zebra.IPRouteBody) family := bgp.RF_IPv6_UC if header.Command == zebra.IPV4_ROUTE_ADD || header.Command == zebra.IPV4_ROUTE_DELETE { family = bgp.RF_IPv4_UC } var nlri bgp.AddrPrefixInterface pattr := make([]bgp.PathAttributeInterface, 0) var mpnlri *bgp.PathAttributeMpReachNLRI var isWithdraw bool = header.Command == zebra.IPV4_ROUTE_DELETE || header.Command == zebra.IPV6_ROUTE_DELETE origin := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP) pattr = append(pattr, origin) log.WithFields(log.Fields{ "Topic": "Zebra", "RouteType": body.Type.String(), "Flag": body.Flags.String(), "Message": body.Message, "Prefix": body.Prefix, "PrefixLength": body.PrefixLength, "Nexthop": body.Nexthops, "IfIndex": body.Ifindexs, "Metric": body.Metric, "Distance": body.Distance, "api": header.Command.String(), }).Debugf("create path from ip route message.") switch family { case bgp.RF_IPv4_UC: nlri = bgp.NewIPAddrPrefix(body.PrefixLength, body.Prefix.String()) nexthop := bgp.NewPathAttributeNextHop(body.Nexthops[0].String()) pattr = append(pattr, nexthop) case bgp.RF_IPv6_UC: nlri = bgp.NewIPv6AddrPrefix(body.PrefixLength, body.Prefix.String()) mpnlri = bgp.NewPathAttributeMpReachNLRI(body.Nexthops[0].String(), []bgp.AddrPrefixInterface{nlri}) pattr = append(pattr, mpnlri) default: log.WithFields(log.Fields{ "Topic": "Zebra", }).Errorf("unsupport address family: %s", family) return nil } med := bgp.NewPathAttributeMultiExitDisc(body.Metric) pattr = append(pattr, med) path := table.NewPath(nil, nlri, isWithdraw, pattr, time.Now(), false) path.SetIsFromExternal(true) return path }
func (path *Path) SetNexthop(nexthop net.IP) { attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) if attr != nil { path.setPathAttr(bgp.NewPathAttributeNextHop(nexthop.String())) } attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) if attr != nil { oldNlri := attr.(*bgp.PathAttributeMpReachNLRI) path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nexthop.String(), oldNlri.Value)) } }
func createPathFromIPRouteMessage(m *zebra.Message, peerInfo *table.PeerInfo) *table.Path { header := m.Header body := m.Body.(*zebra.IPRouteBody) isV4 := header.Command == zebra.IPV4_ROUTE_ADD || header.Command == zebra.IPV4_ROUTE_DELETE var nlri bgp.AddrPrefixInterface pattr := make([]bgp.PathAttributeInterface, 0) var mpnlri *bgp.PathAttributeMpReachNLRI var isWithdraw bool = header.Command == zebra.IPV4_ROUTE_DELETE || header.Command == zebra.IPV6_ROUTE_DELETE origin := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP) pattr = append(pattr, origin) log.WithFields(log.Fields{ "Topic": "Zebra", "RouteType": body.Type.String(), "Flag": body.Flags.String(), "Message": body.Message, "Prefix": body.Prefix, "PrefixLength": body.PrefixLength, "Nexthop": body.Nexthops, "IfIndex": body.Ifindexs, "Metric": body.Metric, "Distance": body.Distance, "api": header.Command.String(), }).Debugf("create path from ip route message.") if isV4 { nlri = bgp.NewIPAddrPrefix(body.PrefixLength, body.Prefix.String()) nexthop := bgp.NewPathAttributeNextHop(body.Nexthops[0].String()) pattr = append(pattr, nexthop) } else { nlri = bgp.NewIPv6AddrPrefix(body.PrefixLength, body.Prefix.String()) mpnlri = bgp.NewPathAttributeMpReachNLRI(body.Nexthops[0].String(), []bgp.AddrPrefixInterface{nlri}) pattr = append(pattr, mpnlri) } med := bgp.NewPathAttributeMultiExitDisc(body.Metric) pattr = append(pattr, med) p := table.NewPath(peerInfo, nlri, isWithdraw, pattr, time.Now(), false) p.SetIsFromExternal(true) return p }
func (p *Path) ToGlobal(vrf *Vrf) *Path { nlri := p.GetNlri() nh := p.GetNexthop() switch rf := p.GetRouteFamily(); rf { case bgp.RF_IPv4_UC: n := nlri.(*bgp.IPAddrPrefix) nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd) case bgp.RF_IPv6_UC: n := nlri.(*bgp.IPv6AddrPrefix) nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd) case bgp.RF_EVPN: n := nlri.(*bgp.EVPNNLRI) switch n.RouteType { case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT: old := n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute) new := &bgp.EVPNMacIPAdvertisementRoute{ RD: vrf.Rd, ESI: old.ESI, ETag: old.ETag, MacAddressLength: old.MacAddressLength, MacAddress: old.MacAddress, IPAddressLength: old.IPAddressLength, IPAddress: old.IPAddress, Labels: old.Labels, } nlri = bgp.NewEVPNNLRI(n.RouteType, n.Length, new) case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: old := n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute) new := &bgp.EVPNMulticastEthernetTagRoute{ RD: vrf.Rd, ETag: old.ETag, IPAddressLength: old.IPAddressLength, IPAddress: old.IPAddress, } nlri = bgp.NewEVPNNLRI(n.RouteType, n.Length, new) } default: return p } path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.OriginInfo().timestamp, false) path.SetExtCommunities(vrf.ExportRt, false) path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nh.String(), []bgp.AddrPrefixInterface{nlri})) return path }
func parseRouteToGobgp(route ovsdb.RowUpdate, nexthops map[string]ovsdb.Row) (*api.Path, bool, bool, error) { var nlri bgp.AddrPrefixInterface path := &api.Path{ IsFromExternal: true, Pattrs: make([][]byte, 0), } isWithdraw := false isFromGobgp := false prefix := route.New.Fields["prefix"].(string) safi := route.New.Fields["sub_address_family"].(string) afi := route.New.Fields["address_family"].(string) m := route.New.Fields["metric"].(float64) attrs := route.New.Fields["path_attributes"].(ovsdb.OvsMap).GoMap if attrs["IsFromGobgp"] == "true" { isFromGobgp = true } nh := make([]interface{}, 0) nhId, ok := route.New.Fields["bgp_nexthops"].(ovsdb.UUID) if ok { for id, n := range nexthops { if id == nhId.GoUUID { nh = append(nh, n.Fields["ip_address"]) } } } nexthop := "0.0.0.0" if afi == "ipv6" { nexthop = "::" } if len(nh) == 0 { log.Debug("nexthop addres does not exist") } else if len(nh) == 1 { if net.ParseIP(nh[0].(string)) == nil { return nil, isWithdraw, isFromGobgp, fmt.Errorf("invalid nexthop address") } else { nexthop = nh[0].(string) } } else { return nil, isWithdraw, isFromGobgp, fmt.Errorf("route has multiple nexthop address") } med, _ := bgp.NewPathAttributeMultiExitDisc(uint32(m)).Serialize() path.Pattrs = append(path.Pattrs, med) lpref, err := strconv.Atoi(attrs["BGP_loc_pref"].(string)) if err != nil { return nil, isWithdraw, isFromGobgp, err } localPref, _ := bgp.NewPathAttributeLocalPref(uint32(lpref)).Serialize() path.Pattrs = append(path.Pattrs, localPref) var origin_t int switch attrs["BGP_origin"].(string) { case "i": origin_t = bgp.BGP_ORIGIN_ATTR_TYPE_IGP case "e": origin_t = bgp.BGP_ORIGIN_ATTR_TYPE_EGP case "?": origin_t = bgp.BGP_ORIGIN_ATTR_TYPE_INCOMPLETE default: return nil, isWithdraw, isFromGobgp, fmt.Errorf("invalid origin") } origin, _ := bgp.NewPathAttributeOrigin(uint8(origin_t)).Serialize() path.Pattrs = append(path.Pattrs, origin) switch afi { case "ipv4", "ipv6": ip, net, err := net.ParseCIDR(prefix) if err != nil { return nil, isWithdraw, isFromGobgp, err } ones, _ := net.Mask.Size() if afi == "ipv4" { if ip.To4() == nil { return nil, isWithdraw, isFromGobgp, fmt.Errorf("invalid ipv4 prefix") } nlri = bgp.NewIPAddrPrefix(uint8(ones), ip.String()) } else { if ip.To16() == nil { return nil, isWithdraw, isFromGobgp, fmt.Errorf("invalid ipv6 prefix") } nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String()) } default: return nil, isWithdraw, isFromGobgp, fmt.Errorf("unsupported address family: %s", afi) } if afi == "ipv4" && safi == "unicast" { path.Nlri, _ = nlri.Serialize() n, _ := bgp.NewPathAttributeNextHop(nexthop).Serialize() path.Pattrs = append(path.Pattrs, n) } else { mpreach, _ := bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri}).Serialize() path.Pattrs = append(path.Pattrs, mpreach) } if attrs["BGP_flags"].(string) == "512" { isWithdraw = true } return path, isWithdraw, isFromGobgp, nil }
func createRequestFromIPRouteMessage(m *zebra.Message) *api.AddPathRequest { header := m.Header body := m.Body.(*zebra.IPRouteBody) family := bgp.RF_IPv6_UC if header.Command == zebra.IPV4_ROUTE_ADD || header.Command == zebra.IPV4_ROUTE_DELETE { family = bgp.RF_IPv4_UC } var nlri bgp.AddrPrefixInterface pattr := make([]bgp.PathAttributeInterface, 0) var mpnlri *bgp.PathAttributeMpReachNLRI var isWithdraw bool = header.Command == zebra.IPV4_ROUTE_DELETE || header.Command == zebra.IPV6_ROUTE_DELETE origin := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP) pattr = append(pattr, origin) log.WithFields(log.Fields{ "Topic": "Zebra", "RouteType": body.Type.String(), "Flag": body.Flags.String(), "Message": body.Message, "Prefix": body.Prefix, "PrefixLength": body.PrefixLength, "Nexthop": body.Nexthops, "IfIndex": body.Ifindexs, "Metric": body.Metric, "Distance": body.Distance, "api": header.Command.String(), }).Debugf("create path from ip route message.") switch family { case bgp.RF_IPv4_UC: nlri = bgp.NewIPAddrPrefix(body.PrefixLength, body.Prefix.String()) nexthop := bgp.NewPathAttributeNextHop(body.Nexthops[0].String()) pattr = append(pattr, nexthop) case bgp.RF_IPv6_UC: nlri = bgp.NewIPv6AddrPrefix(body.PrefixLength, body.Prefix.String()) mpnlri = bgp.NewPathAttributeMpReachNLRI(body.Nexthops[0].String(), []bgp.AddrPrefixInterface{nlri}) pattr = append(pattr, mpnlri) default: log.WithFields(log.Fields{ "Topic": "Zebra", }).Errorf("unsupport address family: %s", family) return nil } med := bgp.NewPathAttributeMultiExitDisc(body.Metric) pattr = append(pattr, med) binPattrs := make([][]byte, 0, len(pattr)) for _, a := range pattr { bin, _ := a.Serialize() binPattrs = append(binPattrs, bin) } binNlri, _ := nlri.Serialize() path := &api.Path{ Nlri: binNlri, Pattrs: binPattrs, IsWithdraw: isWithdraw, Family: uint32(family), IsFromExternal: true, } return &api.AddPathRequest{ Resource: api.Resource_GLOBAL, Path: path, } }
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 (s *Server) api2PathList(resource Resource, ApiPathList []*Path) ([]*table.Path, error) { var nlri bgp.AddrPrefixInterface var nexthop string var pi *table.PeerInfo pathList := make([]*table.Path, 0, len(ApiPathList)) for _, path := range ApiPathList { seen := make(map[bgp.BGPAttrType]bool) pattr := make([]bgp.PathAttributeInterface, 0) extcomms := make([]bgp.ExtendedCommunityInterface, 0) if path.SourceAsn != 0 { pi = &table.PeerInfo{ AS: path.SourceAsn, LocalID: net.ParseIP(path.SourceId), } } if len(path.Nlri) > 0 { nlri = &bgp.IPAddrPrefix{} err := nlri.DecodeFromBytes(path.Nlri) if err != nil { return nil, err } } for _, attr := range path.Pattrs { p, err := bgp.GetPathAttribute(attr) if err != nil { return nil, err } err = p.DecodeFromBytes(attr) if err != nil { return nil, err } if _, ok := seen[p.GetType()]; !ok { seen[p.GetType()] = true } else { return nil, fmt.Errorf("the path attribute apears twice. Type : " + strconv.Itoa(int(p.GetType()))) } switch p.GetType() { case bgp.BGP_ATTR_TYPE_NEXT_HOP: nexthop = p.(*bgp.PathAttributeNextHop).Value.String() case bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES: value := p.(*bgp.PathAttributeExtendedCommunities).Value if len(value) > 0 { extcomms = append(extcomms, value...) } case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI: mpreach := p.(*bgp.PathAttributeMpReachNLRI) if len(mpreach.Value) != 1 { return nil, fmt.Errorf("include only one route in mp_reach_nlri") } nlri = mpreach.Value[0] nexthop = mpreach.Nexthop.String() default: pattr = append(pattr, p) } } if nlri == nil || nexthop == "" { return nil, fmt.Errorf("not found nlri or nexthop") } rf := bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()) if resource != Resource_VRF && rf == bgp.RF_IPv4_UC { pattr = append(pattr, bgp.NewPathAttributeNextHop(nexthop)) } else { pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri})) } if len(extcomms) > 0 { pattr = append(pattr, bgp.NewPathAttributeExtendedCommunities(extcomms)) } newPath := table.NewPath(pi, nlri, path.IsWithdraw, pattr, time.Now(), path.NoImplicitWithdraw) newPath.SetIsFromExternal(path.IsFromExternal) pathList = append(pathList, newPath) } return pathList, 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 }
func createUpdateMsgFromPath(path *Path, msg *bgp.BGPMessage) *bgp.BGPMessage { rf := path.GetRouteFamily() if rf == bgp.RF_IPv4_UC { nlri := path.GetNlri().(*bgp.IPAddrPrefix) if path.IsWithdraw { if msg != nil { u := msg.Body.(*bgp.BGPUpdate) u.WithdrawnRoutes = append(u.WithdrawnRoutes, nlri) return nil } else { return bgp.NewBGPUpdateMessage([]*bgp.IPAddrPrefix{nlri}, nil, nil) } } else { if msg != nil { u := msg.Body.(*bgp.BGPUpdate) u.NLRI = append(u.NLRI, nlri) } else { pathAttrs := path.GetPathAttrs() return bgp.NewBGPUpdateMessage(nil, pathAttrs, []*bgp.IPAddrPrefix{nlri}) } } } else { if path.IsWithdraw { if msg != nil { u := msg.Body.(*bgp.BGPUpdate) for _, p := range u.PathAttributes { if p.GetType() == bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI { unreach := p.(*bgp.PathAttributeMpUnreachNLRI) unreach.Value = append(unreach.Value, path.GetNlri()) } } } else { var nlris []bgp.AddrPrefixInterface attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) if attr == nil { // for bmp post-policy attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI) nlris = attr.(*bgp.PathAttributeMpUnreachNLRI).Value } else { nlris = []bgp.AddrPrefixInterface{path.GetNlri()} } clonedAttrs := path.GetPathAttrs() for i, a := range clonedAttrs { if a.GetType() == bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI || a.GetType() == bgp.BGP_ATTR_TYPE_MP_REACH_NLRI { clonedAttrs[i] = bgp.NewPathAttributeMpUnreachNLRI(nlris) break } } return bgp.NewBGPUpdateMessage(nil, clonedAttrs, nil) } } else { if msg != nil { u := msg.Body.(*bgp.BGPUpdate) for _, p := range u.PathAttributes { if p.GetType() == bgp.BGP_ATTR_TYPE_MP_REACH_NLRI { reach := p.(*bgp.PathAttributeMpReachNLRI) reach.Value = append(reach.Value, path.GetNlri()) } } } else { attrs := make([]bgp.PathAttributeInterface, 0, 8) for _, p := range path.GetPathAttrs() { if p.GetType() == bgp.BGP_ATTR_TYPE_MP_REACH_NLRI { attrs = append(attrs, bgp.NewPathAttributeMpReachNLRI(path.GetNexthop().String(), []bgp.AddrPrefixInterface{path.GetNlri()})) } else { attrs = append(attrs, p) } } // we don't need to clone here but we // might merge path to this message in // the future so let's clone anyway. return bgp.NewBGPUpdateMessage(nil, attrs, nil) } } } return nil }
//AddLocalProtoRoute is used to add local endpoint to the protocol RIB func (self *OfnetBgp) AddLocalProtoRoute(pathInfo *OfnetProtoRouteInfo) error { log.Infof("Received AddLocalProtoRoute to add local endpoint to protocol RIB: %v", pathInfo) if self.routerIP == "" { //ignoring populating to the bgp rib because //Bgp is not configured. return nil } path := &api.Path{ Pattrs: make([][]byte, 0), SourceAsn: self.myBgpAs, } aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{self.myBgpAs})} aspath, _ := bgp.NewPathAttributeAsPath(aspathParam).Serialize() path.Pattrs = append(path.Pattrs, aspath) // form the path structure with appropriate path attributes nlri := bgp.NewIPAddrPrefix(32, pathInfo.localEpIP) path.Nlri, _ = nlri.Serialize() origin, _ := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_EGP).Serialize() path.Pattrs = append(path.Pattrs, origin) log.Infof("Received AddLocalProtoRoute aspath: %v", aspath) mpls, err := bgp.ParseMPLSLabelStack("3") if err != nil { return nil } var nlri2 bgp.AddrPrefixInterface nlri2 = bgp.NewLabeledIPAddrPrefix(32, pathInfo.localEpIP, *mpls) mpreach, _ := bgp.NewPathAttributeMpReachNLRI(pathInfo.nextHopIP, []bgp.AddrPrefixInterface{nlri2}).Serialize() log.Infof("Received AddLocalProtoRoute nlri2: %v, mpreach: %v", nlri2, mpreach) path.Pattrs = append(path.Pattrs, mpreach) //path.Pattrs = append(path.Pattrs, n) arg := &api.AddPathRequest{ Resource: api.Resource_GLOBAL, VrfId: "default", Path: path, } log.Infof("BGP - arg %v ", arg) // add routes /* prefix := pathInfo.localEpIP log.Infof("BGP - Prefix %v " , prefix ) path2, err := cmd.ParsePath(bgp.RF_IPv4_MPLS, []string{"10.200.1.25/32", "3"}) log.Infof("BGP - Path2 %v " , path2 ) log.Infof("BGP - Err %v " , err ) req := bgpserver.NewGrpcRequest(bgpserver.REQ_ADD_PATH, "", bgp.RouteFamily(0), &api.AddPathRequest{ Resource: api.Resource_GLOBAL, Path: path2, }) self.bgpServer.GrpcReqCh <- req res := <-req.ResponseCh if err := res.Err(); err != nil { log.Fatal(err) log.Infof("BGP - Err %v " , err) } */ //send arguement stream client := api.NewGobgpApiClient(self.cc) if client == nil { log.Infof("Gobgpapi stream invalid") return nil } stream, err := client.AddPath(context.Background(), arg) if err != nil { log.Infof("Fail to enforce Modpath: %v %v", err, stream) return err } return nil }