func (v *ripVrf) localRouteDel(n *ripNet) { log.Printf("ripVrf.localRouteDel: vrf[%s]: %v", v.name, n) count := 0 now := time.Now() for _, route := range v.routes { if route.srcExternal { continue // do not remove external routes } if !route.isValid(now) { continue // ignore expired routes } if !addr.NetEqual(&n.addr, &route.addr) { continue // ignore routes for other prefixes } if !n.nexthop.Equal(route.nexthop) { continue // ignore routes for other nexthops } if n.metric != route.metric { log.Printf("ripVrf.localRouteDel: internal error: wrong metric=%d: vrf=[%s]: %v", route.metric, v.name, route) } route.disable(now) count++ if count > 1 { log.Printf("ripVrf.localRouteDel: internal error: removed multiple routes: count=%d: vrf=[%s]: %v", count, v.name, route) } } }
func (v *ripVrf) netGet(prefix *net.IPNet) (int, *ripNet) { for i, n := range v.nets { if addr.NetEqual(prefix, &n.addr) { return i, n } } return -1, nil }
func (v *ripVrf) nexthopGet(prefix *net.IPNet, nexthop net.IP) (int, *ripNet) { for i, n := range v.nets { if nexthop.Equal(n.nexthop) == addr.NetEqual(prefix, &n.addr) { return i, n } } return -1, nil }
// FIXME localRouteAdd(): called indirectly from main goroutine, but calls route.disable() func (v *ripVrf) localRouteAdd(n *ripNet, r *RipRouter) { //log.Printf("ripVrf.localRouteAdd: vrf[%s]: %v", v.name, n) deleteList := []*ripRoute{} now := time.Now() for _, route := range v.routes { if !route.isValid(now) { continue // ignore invalid routes } if !addr.NetEqual(&n.addr, &route.addr) { continue // ignore routes for other prefixes } if n.metric > route.metric { return // found better metric -- refuse to change routing table } if n.metric < route.metric { // new route has better metric: delete existing routes deleteList = append(deleteList, route) continue } // new route has equal metric: keep existing routes if n.nexthop.Equal(route.nexthop) { log.Printf("ripVrf.localRouteAdd: internal error: duplicate prefix/nexthop/metric: vrf=[%s] route: %v", v.name, route) continue } } // delete existing routes for _, route := range deleteList { route.disable(now) } // add route newRoute := newRipRoute(n.addr, n.nexthop, n.metric, now, r) v.routeAdd(newRoute) }
func (r *RipRouter) lookupAddressFirstMatch(vrfname string, netaddr net.IPNet) (*ripRoute, error) { defer r.vrfMutex.Unlock() r.vrfMutex.Lock() _, v := r.vrfGet(vrfname) if v == nil { return nil, fmt.Errorf("lookupAddressFirstMatch: VRF not found: vrf=[%s]", vrfname) } now := time.Now() for _, route := range v.routes { if !route.isValid(now) { continue } if addr.NetEqual(&route.addr, &netaddr) { return route, nil } } return nil, fmt.Errorf("lookupAddressFirstMatch: prefix not found: vrf=[%s] prefix=[%v]", vrfname, &netaddr) }
func (r *RipRouter) extRouteAdd(vrfname string, tag uint16, netaddr net.IPNet, nexthop net.IP, metric, ifindex int, ifname string, router net.IP) { defer r.vrfMutex.Unlock() r.vrfMutex.Lock() _, v := r.vrfGet(vrfname) if v == nil { log.Printf("RipRouter.routeAdd: VRF not found: vrf=[%s]", vrfname) return } now := time.Now() for _, route := range v.routes { if !route.isValid(now) { continue // ignore invalid routes } if !addr.NetEqual(&netaddr, &route.addr) { continue // ignore routes for other prefixes } /* If there is an existing route, compare the next hop address to the address of the router from which the datagram came. If this datagram is from the same router as the existing route, reinitialize the timeout. */ sameNexthop := route.nexthop.Equal(router) if sameNexthop { route.resetTimer(now) } if metric < route.metric { // new route will be better, remove the old (current) one route.disable(now) continue } if sameNexthop { // same prefix/nexthop if metric != route.metric { // only update metric route.metric = metric route.routeChanged = true r.trigUpdate(now) // schedule triggered update } // else: exact same prefix/nexthop/metric: do nothing (timer was reset above) return // do not add route below } // distinct nexthop if metric > route.metric { return // new nexthop with worse metric: do not add route below } // distinc nexthop with same metric: could add route below as ECMP } // add new external route if metric == RIP_METRIC_INFINITY { return // refuse to add new route with metric infinity } // Set the next hop address to be the address of the router // from which the datagram came newNexthop := router newRoute := newRipRoute(netaddr, newNexthop, metric, now, r) newRoute.srcExternal = true newRoute.srcIfIndex = ifindex newRoute.srcIfName = ifname newRoute.srcRouter = router v.routeAdd(newRoute) }