func applyPolicy(component, owner string, d Direction, policies []*policy.Policy, original *table.Path) (bool, *table.Path) { var applied bool = true for _, pol := range policies { if result, action, newpath := pol.Apply(original); result { log.Debug("newpath: ", newpath) if action == policy.ROUTE_TYPE_REJECT { log.WithFields(log.Fields{ "Topic": component, "Key": owner, "NRLI": original.GetNlri(), "Dir": d, }).Debug("path was rejected") // return applied, nil, this means path was rejected return applied, nil } else { // return applied, new path return applied, newpath } } } log.WithFields(log.Fields{ "Topic": component, "Key": owner, "Len": len(policies), "NRLI": original, "Dir": d, }).Debug("no policy applied") return !applied, original }
func ToPathApi(path *table.Path) *Path { nlri := path.GetNlri() n, _ := nlri.Serialize() family := uint32(bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI())) pattrs := func(arg []bgp.PathAttributeInterface) [][]byte { ret := make([][]byte, 0, len(arg)) for _, a := range arg { aa, _ := a.Serialize() ret = append(ret, aa) } return ret }(path.GetPathAttrs()) return &Path{ Nlri: n, Pattrs: pattrs, Age: path.GetTimestamp().Unix(), IsWithdraw: path.IsWithdraw, Validation: int32(path.Validation().ToInt()), Filtered: path.Filtered("") == table.POLICY_DIRECTION_IN, Family: family, SourceAsn: path.GetSource().AS, SourceId: path.GetSource().ID.String(), NeighborIp: path.GetSource().Address.String(), Stale: path.IsStale(), IsFromExternal: path.IsFromExternal(), } }
func newIPRouteMessage(path *table.Path) *zebra.Message { l := strings.SplitN(path.GetNlri().String(), "/", 2) var command zebra.API_TYPE var prefix net.IP nexthops := []net.IP{} switch path.GetRouteFamily() { case bgp.RF_IPv4_UC: if path.IsWithdraw == true { command = zebra.IPV4_ROUTE_DELETE } else { command = zebra.IPV4_ROUTE_ADD } prefix = net.ParseIP(l[0]).To4() nexthops = append(nexthops, path.GetNexthop().To4()) case bgp.RF_IPv6_UC: if path.IsWithdraw == true { command = zebra.IPV6_ROUTE_DELETE } else { command = zebra.IPV6_ROUTE_ADD } prefix = net.ParseIP(l[0]).To16() nexthops = append(nexthops, path.GetNexthop().To16()) default: return nil } flags := uint8(zebra.MESSAGE_NEXTHOP) plen, _ := strconv.Atoi(l[1]) med, err := path.GetMed() if err == nil { flags |= zebra.MESSAGE_METRIC } return &zebra.Message{ Header: zebra.Header{ Len: zebra.HEADER_SIZE, Marker: zebra.HEADER_MARKER, Version: zebra.VERSION, Command: command, }, Body: &zebra.IPRouteBody{ Type: zebra.ROUTE_BGP, SAFI: zebra.SAFI_UNICAST, Message: flags, Prefix: prefix, PrefixLength: uint8(plen), Nexthops: nexthops, Metric: med, }, } }
func path2data(path *table.Path) (map[string]interface{}, map[string]string) { fields := map[string]interface{}{ "RouterID": path.GetSource().ID, } if asPath := path.GetAsPath(); asPath != nil { fields["ASPath"] = asPath.String() } if origin, err := path.GetOrigin(); err == nil { typ := "-" switch origin { case bgp.BGP_ORIGIN_ATTR_TYPE_IGP: typ = "i" case bgp.BGP_ORIGIN_ATTR_TYPE_EGP: typ = "e" case bgp.BGP_ORIGIN_ATTR_TYPE_INCOMPLETE: typ = "?" } fields["Origin"] = typ } if med, err := path.GetMed(); err == nil { fields["Med"] = med } tags := map[string]string{ "PeerAddress": path.GetSource().Address.String(), "PeerAS": fmt.Sprintf("%v", path.GetSource().AS), "Timestamp": path.GetTimestamp().String(), } if nexthop := path.GetNexthop(); len(nexthop) > 0 { fields["NextHop"] = nexthop.String() } if originAS := path.GetSourceAs(); originAS != 0 { fields["OriginAS"] = fmt.Sprintf("%v", originAS) } if err := bgp.FlatUpdate(tags, path.GetNlri().Flat()); err != nil { log.Error(err) } for _, p := range path.GetPathAttrs() { if err := bgp.FlatUpdate(tags, p.Flat()); err != nil { log.Error(err) } } return fields, tags }
func path2data(path *table.Path) (map[string]interface{}, map[string]string) { fields := map[string]interface{}{ "ASPath": path.GetAsPath().String(), } if origin, err := path.GetOrigin(); err == nil { typ := "-" switch origin { case bgp.BGP_ORIGIN_ATTR_TYPE_IGP: typ = "i" case bgp.BGP_ORIGIN_ATTR_TYPE_EGP: typ = "e" case bgp.BGP_ORIGIN_ATTR_TYPE_INCOMPLETE: typ = "?" } fields["Origin"] = typ } if med, err := path.GetMed(); err == nil { fields["Med"] = med } var prefix, prefixLen string l := strings.Split(path.GetNlri().String(), "/") if len(l) == 2 { prefix = l[0] prefixLen = l[1] } tags := map[string]string{ "PeerAddress": path.GetSource().Address.String(), "PeerAS": fmt.Sprintf("%v", path.GetSource().AS), "Prefix": prefix, "PrefixLen": prefixLen, "NextHop": path.GetNexthop().String(), "OriginAS": fmt.Sprintf("%v", path.GetSourceAs()), "Timestamp": path.GetTimestamp().String(), } return fields, tags }
func ipPrefixCalculate(path *table.Path, cPrefix Prefix) bool { rf := path.GetRouteFamily() log.Debug("path routefamily : ", rf.String()) var pAddr net.IP var pMasklen uint8 if rf != cPrefix.AddressFamily { return false } switch rf { case bgp.RF_IPv4_UC: pAddr = path.GetNlri().(*bgp.NLRInfo).IPAddrPrefix.Prefix pMasklen = path.GetNlri().(*bgp.NLRInfo).IPAddrPrefix.Length case bgp.RF_IPv6_UC: pAddr = path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix pMasklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length default: return false } cp := fmt.Sprintf("%s/%d", cPrefix.Address, cPrefix.Masklength) rMin, okMin := cPrefix.MasklengthRange[MASK_LENGTH_RANGE_MIN] rMax, okMax := cPrefix.MasklengthRange[MASK_LENGTH_RANGE_MAX] if !okMin && !okMax { if pAddr.Equal(cPrefix.Address) && pMasklen == cPrefix.Masklength { return true } else { return false } } _, ipNet, e := net.ParseCIDR(cp) if e != nil { log.WithFields(log.Fields{ "Topic": "Policy", "Prefix": ipNet, "Error": e, }).Error("failed to parse the prefix of condition") return false } if ipNet.Contains(pAddr) && (rMin <= pMasklen && pMasklen <= rMax) { return true } return false }
//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 }