Пример #1
0
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
}
Пример #2
0
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
}
Пример #3
0
func TestBMP(t *testing.T) {
	aspath1 := []bgp.AsPathParamInterface{
		bgp.NewAs4PathParam(2, []uint32{1000000}),
		bgp.NewAs4PathParam(1, []uint32{1000001, 1002}),
		bgp.NewAs4PathParam(2, []uint32{1003, 100004}),
	}
	mp_nlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(100,
		"fe80:1234:1234:5667:8967:af12:8912:1023")}

	p := []bgp.PathAttributeInterface{
		bgp.NewPathAttributeOrigin(3),
		bgp.NewPathAttributeAsPath(aspath1),
		bgp.NewPathAttributeMpUnreachNLRI(mp_nlri),
	}
	w := []*bgp.IPAddrPrefix{}
	n := []*bgp.IPAddrPrefix{}

	msg := bgp.NewBGPUpdateMessage(w, p, n)
	pList := ProcessMessage(msg, peerR1(), time.Now())
	CreateUpdateMsgFromPaths(pList)
}
Пример #4
0
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
}
Пример #5
0
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,
	}

}
Пример #6
0
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
}
Пример #7
0
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
}