Beispiel #1
0
func (e *RibEntry) DecodeFromBytes(data []byte) ([]byte, error) {
	notAllBytesAvail := fmt.Errorf("not all RibEntry bytes are available")
	if len(data) < 8 {
		return nil, notAllBytesAvail
	}
	e.PeerIndex = binary.BigEndian.Uint16(data[:2])
	e.OriginatedTime = binary.BigEndian.Uint32(data[2:6])
	totalLen := binary.BigEndian.Uint16(data[6:8])
	data = data[8:]
	for attrLen := totalLen; attrLen > 0; {
		p, err := bgp.GetPathAttribute(data)
		if err != nil {
			return nil, err
		}
		err = p.DecodeFromBytes(data)
		if err != nil {
			return nil, err
		}
		attrLen -= uint16(p.Len())
		if len(data) < p.Len() {
			return nil, notAllBytesAvail
		}
		data = data[p.Len():]
		e.PathAttributes = append(e.PathAttributes, p)
	}
	return data, nil
}
Beispiel #2
0
func ApiStruct2Path(p *gobgpapi.Path) ([]*Path, error) {
	nlris := make([]bgp.AddrPrefixInterface, 0, 1)
	data := p.Nlri
	if p.Family == uint32(bgp.RF_IPv4_UC) && len(data) > 0 {
		nlri := &bgp.IPAddrPrefix{}
		err := nlri.DecodeFromBytes(data)
		if err != nil {
			return nil, err
		}
		nlris = append(nlris, nlri)
	}

	pattr := make([]bgp.PathAttributeInterface, 0, len(p.Pattrs))
	for _, attr := range p.Pattrs {
		p, err := bgp.GetPathAttribute(attr)
		if err != nil {
			return nil, err
		}

		err = p.DecodeFromBytes(attr)
		if err != nil {
			return nil, err
		}

		switch p.GetType() {
		case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI:
			mpreach := p.(*bgp.PathAttributeMpReachNLRI)
			for _, nlri := range mpreach.Value {
				nlris = append(nlris, nlri)
			}
		}
		pattr = append(pattr, p)
	}

	paths := make([]*Path, 0, len(nlris))
	for _, nlri := range nlris {
		paths = append(paths, &Path{
			Nlri:       nlri,
			PathAttrs:  pattr,
			Age:        p.Age,
			Best:       p.Best,
			IsWithdraw: p.IsWithdraw,
			Validation: p.Validation,
			SourceId:   p.SourceId,
			NeighborIp: p.NeighborIp,
			Filtered:   p.Filtered,
			Stale:      p.Stale,
		})
	}
	return paths, nil
}
Beispiel #3
0
func ApiStruct2Path(p *gobgpapi.Path) ([]*Path, error) {
	nlris := make([]bgp.AddrPrefixInterface, 0, 1)
	if len(p.Nlri) == 0 {
		return nil, fmt.Errorf("path doesn't have nlri")
	}
	afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(p.Family))
	nlri, err := bgp.NewPrefixFromRouteFamily(afi, safi)
	if err != nil {
		return nil, err
	}

	if err := nlri.DecodeFromBytes(p.Nlri); err != nil {
		return nil, err
	}
	nlris = append(nlris, nlri)

	pattr := make([]bgp.PathAttributeInterface, 0, len(p.Pattrs))
	for _, attr := range p.Pattrs {
		p, err := bgp.GetPathAttribute(attr)
		if err != nil {
			return nil, err
		}

		err = p.DecodeFromBytes(attr)
		if err != nil {
			return nil, err
		}
		pattr = append(pattr, p)
	}

	paths := make([]*Path, 0, len(nlris))
	for _, nlri := range nlris {
		paths = append(paths, &Path{
			Nlri:       nlri,
			PathAttrs:  pattr,
			Age:        p.Age,
			Best:       p.Best,
			IsWithdraw: p.IsWithdraw,
			Validation: p.Validation,
			SourceId:   p.SourceId,
			NeighborIp: p.NeighborIp,
			Filtered:   p.Filtered,
			Stale:      p.Stale,
		})
	}
	return paths, nil
}
Beispiel #4
0
//export decode_path
func decode_path(p *C.path) *C.char {
	var buf []byte
	var nlri bgp.AddrPrefixInterface
	if p.nlri.len > 0 {
		buf = []byte(C.GoStringN(p.nlri.value, p.nlri.len))
		nlri = &bgp.IPAddrPrefix{}
		err := nlri.DecodeFromBytes(buf)
		if err != nil {
			return nil
		}
	}
	pattrs := make([]bgp.PathAttributeInterface, 0, int(p.path_attributes_len))
	for i := 0; i < int(p.path_attributes_len); i++ {
		b := C.get_path_attribute(p, C.int(i))
		buf = []byte(C.GoStringN(b.value, b.len))
		pattr, err := bgp.GetPathAttribute(buf)
		if err != nil {
			return nil
		}

		err = pattr.DecodeFromBytes(buf)
		if err != nil {
			return nil
		}

		switch pattr.GetType() {
		case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI:
			mpreach := pattr.(*bgp.PathAttributeMpReachNLRI)
			if len(mpreach.Value) != 1 {
				return nil
			}
			nlri = mpreach.Value[0]
		}

		pattrs = append(pattrs, pattr)
	}
	j, _ := json.Marshal(struct {
		Nlri      bgp.AddrPrefixInterface      `json:"nlri"`
		PathAttrs []bgp.PathAttributeInterface `json:"attrs"`
	}{
		Nlri:      nlri,
		PathAttrs: pattrs,
	})
	return C.CString(string(j))
}
Beispiel #5
0
func (p *Path) ToNativePath(option ...ToNativeOption) (*table.Path, error) {
	info := &table.PeerInfo{
		AS:      p.SourceAsn,
		ID:      net.ParseIP(p.SourceId),
		Address: net.ParseIP(p.NeighborIp),
	}
	var nlri bgp.AddrPrefixInterface
	for _, o := range option {
		info.LocalAS = o.LocalAS
		info.LocalID = o.LocalID
		info.RouteReflectorClient = o.RouteReflectorClient
		info.RouteReflectorClusterID = o.RouteReflectorClusterID
		nlri = o.NLRI
	}
	if nlri == nil {
		var err error
		nlri, err = getNLRI(bgp.RouteFamily(p.Family), p.Nlri)
		if err != nil {
			return nil, err
		}
	}
	pattr := make([]bgp.PathAttributeInterface, 0, len(p.Pattrs))
	for _, attr := range p.Pattrs {
		p, err := bgp.GetPathAttribute(attr)
		if err != nil {
			return nil, err
		}
		err = p.DecodeFromBytes(attr)
		if err != nil {
			return nil, err
		}
		pattr = append(pattr, p)
	}
	t := time.Unix(p.Age, 0)
	path := table.NewPath(info, nlri, p.IsWithdraw, pattr, t, false)
	path.SetValidation(config.IntToRpkiValidationResultTypeMap[int(p.Validation)])
	path.MarkStale(p.Stale)
	if p.Filtered {
		path.Filter("", table.POLICY_DIRECTION_IN)
	}
	return path, nil
}
Beispiel #6
0
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
}
Beispiel #7
0
//modrib receives route updates from BGP server and adds the endpoint
func (self *OfnetBgp) modRib(path *api.Path) error {
	var nlri bgp.AddrPrefixInterface
	var nextHop string
	var macAddrStr string
	var portNo uint32
	if len(path.Nlri) > 0 {
		nlri = &bgp.IPAddrPrefix{}
		err := nlri.DecodeFromBytes(path.Nlri)
		if err != nil {
			return err
		}
	}

	for _, attr := range path.Pattrs {
		p, err := bgp.GetPathAttribute(attr)
		if err != nil {
			return err
		}

		err = p.DecodeFromBytes(attr)
		if err != nil {
			return err
		}

		if p.GetType() == bgp.BGP_ATTR_TYPE_NEXT_HOP {
			nextHop = p.(*bgp.PathAttributeNextHop).Value.String()
			break
		}
	}
	if nextHop == "0.0.0.0" {
		return nil
	}

	if nlri == nil {
		return fmt.Errorf("no nlri")
	}

	endpointIPNet, _ := netlink.ParseIPNet(nlri.String())
	log.Infof("Bgp Rib Received endpoint update for %v , with nexthop %v",
		endpointIPNet, nextHop)
	if endpointIPNet == nil {
		return nil
	}
	//check if bgp published a route local to the host
	epid := self.agent.getEndpointIdByIpVrf(endpointIPNet.IP.Mask(endpointIPNet.Mask), "default")

	//Check if the route is local
	if nextHop == self.routerIP {
		log.Info("This is a local route skipping endpoint create! ")
		return nil
	} else if self.agent.endpointDb[epid] != nil {
		if self.agent.endpointDb[epid].EndpointType != "external" {
			log.Info("Endpoint was learnt via internal protocol. skipping update! ")
			return nil
		}
	}
	nhEpid := self.agent.getEndpointIdByIpVrf(net.ParseIP(nextHop), "default")
	if self.agent.endpointDb[nhEpid] == nil {
		//the nexthop is not the directly connected eBgp peer
		macAddrStr = ""
		portNo = 0
	} else {
		macAddrStr = self.agent.endpointDb[nhEpid].MacAddrStr
		portNo = self.agent.endpointDb[nhEpid].PortNo
	}

	ipmask := net.ParseIP("255.255.255.255").Mask(endpointIPNet.Mask)

	if path.IsWithdraw != true {
		epreg := &OfnetEndpoint{
			EndpointID:   epid,
			EndpointType: "external",
			IpAddr:       endpointIPNet.IP,
			IpMask:       ipmask,
			Vrf:          "default", // FIXME set VRF correctly
			MacAddrStr:   macAddrStr,
			Vlan:         1,
			OriginatorIp: self.agent.localIp,
			PortNo:       portNo,
			Timestamp:    time.Now(),
		}

		// Install the endpoint in datapath
		// First, add the endpoint to local routing table
		self.agent.endpointDb[epreg.EndpointID] = epreg
		err := self.agent.datapath.AddEndpoint(epreg)
		if err != nil {
			log.Errorf("Error adding endpoint: {%+v}. Err: %v", epreg, err)
			return err
		}
	} else {
		log.Info("Received route withdraw from BGP for ", endpointIPNet)
		endpoint := self.agent.getEndpointByIpVrf(endpointIPNet.IP, "default")
		if endpoint != nil {
			self.agent.datapath.RemoveEndpoint(endpoint)
			delete(self.agent.endpointDb, endpoint.EndpointID)
		}
	}
	return nil
}