Beispiel #1
0
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)
		}
	}
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
// 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)
}
Beispiel #5
0
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)
}
Beispiel #6
0
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)
}