func NewDestination(nlri bgp.AddrPrefixInterface) *Destination { d := &Destination{ routeFamily: bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()), nlri: nlri, knownPathList: make([]*Path, 0), withdrawList: make([]*Path, 0), newPathList: make([]*Path, 0), } switch d.routeFamily { case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: d.RadixKey = CidrToRadixkey(nlri.String()) } return d }
func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, timestamp time.Time, noImplicitWithdraw bool) *Path { if !isWithdraw && pattrs == nil { log.WithFields(log.Fields{ "Topic": "Table", "Key": nlri.String(), "Peer": source.Address.String(), }).Error("Need to provide patattrs for the path that is not withdraw.") return nil } if nlri != nil && (nlri.SAFI() == bgp.SAFI_FLOW_SPEC_UNICAST || nlri.SAFI() == bgp.SAFI_FLOW_SPEC_VPN) { var coms FlowSpecComponents var f *bgp.FlowSpecNLRI switch nlri.(type) { case *bgp.FlowSpecIPv4Unicast: f = &nlri.(*bgp.FlowSpecIPv4Unicast).FlowSpecNLRI case *bgp.FlowSpecIPv4VPN: f = &nlri.(*bgp.FlowSpecIPv4VPN).FlowSpecNLRI case *bgp.FlowSpecIPv6Unicast: f = &nlri.(*bgp.FlowSpecIPv6Unicast).FlowSpecNLRI case *bgp.FlowSpecIPv6VPN: f = &nlri.(*bgp.FlowSpecIPv6VPN).FlowSpecNLRI } if f != nil { coms = f.Value sort.Sort(coms) } } return &Path{ info: &originInfo{ nlri: nlri, source: source, timestamp: timestamp, noImplicitWithdraw: noImplicitWithdraw, }, IsWithdraw: isWithdraw, pathAttrs: pattrs, filtered: make(map[string]PolicyDirection), } }
func (t *Table) tableKey(nlri bgp.AddrPrefixInterface) string { return nlri.String() }
//modrib receives route updates from BGP server and adds the endpoint func (self *OfnetBgp) modRib(path *table.Path) error { var nlri bgp.AddrPrefixInterface var nextHop string var macAddrStr string var portNo uint32 nlri = path.GetNlri() nextHop = path.GetNexthop().String() 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 path %s", path.String()) //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.Debugf("This is a local route skipping endpoint create! ") return nil } else if ep := self.agent.getEndpointByID(epid); ep != nil { if ep.EndpointType != "external" { log.Debugf("Endpoint was learnt via internal protocol. skipping update! ") return nil } } nhEpid := self.agent.getEndpointIdByIpVrf(net.ParseIP(nextHop), "default") if ep := self.agent.getEndpointByID(nhEpid); ep == nil { //the nexthop is not the directly connected eBgp peer macAddrStr = "" portNo = 0 } else { macAddrStr = ep.MacAddrStr portNo = ep.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.Set(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) self.agent.endpointDb.Remove(endpoint.EndpointID) } } return nil }
//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 }