示例#1
0
void
rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum)
{
	struct radix_node *rn0, *rn;
	u_int32_t n;
	struct rtentry *rt;
	int64_t weight;

	/*
	 * XXX we don't attempt to lookup cached route again; what should
	 * be done for sendto(3) case?
	 */
	if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)
	    && RT_LINK_IS_UP(ro->ro_rt->rt_ifp))
		return;				 
	ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, 0, fibnum);

	/* if the route does not exist or it is not multipath, don't care */
	if (ro->ro_rt == NULL)
		return;
	if (rn_mpath_next((struct radix_node *)ro->ro_rt) == NULL) {
		RT_UNLOCK(ro->ro_rt);
		return;
	}

	/* beyond here, we use rn as the master copy */
	rn0 = rn = (struct radix_node *)ro->ro_rt;
	n = rn_mpath_count(rn0);

	/* gw selection by Modulo-N Hash (RFC2991) XXX need improvement? */
	hash += hashjitter;
	hash %= n;
	for (weight = abs((int32_t)hash), rt = ro->ro_rt;
	     weight >= rt->rt_weight && rn; 
	     weight -= rt->rt_weight) {
		
		/* stay within the multipath routes */
		if (rn->rn_dupedkey && rn->rn_mask != rn->rn_dupedkey->rn_mask)
			break;
		rn = rn->rn_dupedkey;
		rt = (struct rtentry *)rn;
	}
	/* XXX try filling rt_gwroute and avoid unreachable gw  */

	/* gw selection has failed - there must be only zero weight routes */
	if (!rn) {
		RT_UNLOCK(ro->ro_rt);
		ro->ro_rt = NULL;
		return;
	}
	if (ro->ro_rt != rt) {
		RTFREE_LOCKED(ro->ro_rt);
		ro->ro_rt = (struct rtentry *)rn;
		RT_LOCK(ro->ro_rt);
		RT_ADDREF(ro->ro_rt);

	} 
	RT_UNLOCK(ro->ro_rt);
}
示例#2
0
void
rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum)
{
	struct rtentry *rt;

	/*
	 * XXX we don't attempt to lookup cached route again; what should
	 * be done for sendto(3) case?
	 */
	if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)
	    && RT_LINK_IS_UP(ro->ro_rt->rt_ifp))
		return;				 
	ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, 0, fibnum);

	/* if the route does not exist or it is not multipath, don't care */
	if (ro->ro_rt == NULL)
		return;
	if (rn_mpath_next((struct radix_node *)ro->ro_rt) == NULL) {
		RT_UNLOCK(ro->ro_rt);
		return;
	}

	rt = rt_mpath_selectrte(ro->ro_rt, hash);
	/* XXX try filling rt_gwroute and avoid unreachable gw  */

	/* gw selection has failed - there must be only zero weight routes */
	if (!rt) {
		RT_UNLOCK(ro->ro_rt);
		ro->ro_rt = NULL;
		return;
	}
	if (ro->ro_rt != rt) {
		RTFREE_LOCKED(ro->ro_rt);
		ro->ro_rt = rt;
		RT_LOCK(ro->ro_rt);
		RT_ADDREF(ro->ro_rt);

	} 
	RT_UNLOCK(ro->ro_rt);
}
示例#3
0
struct rtentry *
in6_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum)
{

	return (rtalloc1_fib(dst, report, ignflags, fibnum));
}
示例#4
0
/*
 * Accept by socket(4) in AF_ROUTE received service requests.
 *
 *  o RTAX_DST holds key x for fec = < x, nh > where nh -> ifp
 *
 *  o RTAX_GATEWAY holds by sockaddr_ftn{} for MPLS label
 *    binding necessary 
 *
 *     < seg_i , seg_j > 
 *
 *    tuple where seg_i denotes key for by nhlfe generated ilm, 
 *    Furthermore, seg_j denotes typically upstream label for 
 *    transmission downstream by interface ifp in link-layer.
 *  
 *  o In rt_addrinfo{} Service Primitive (spi) contained flags 
 *    encodes with MPLS label binding linked operation.
 *   
 *     RTF_{POP|PUSH|SWAP} - self expanatory.
 *
 *     RTF_MPE, denotes initial label of Label Switch Path.
 *
 *     RTF_STK, denotes label stacking, but not yet fully
 *     implemented.
 */
int
mpls_rt_output_fib(struct rt_msghdr *rtm, struct rt_addrinfo *rti, 
		struct rtentry **rt, u_int fibnum)
{ 		
	struct rtentry *fec = NULL;
	struct ifnet *ifp = NULL;
	struct mpls_aliasreq ifra;
	int error = 0, cmd = 0;
	
#ifdef MPLS_DEBUG
	(void)printf("%s\n", __func__);
#endif /* MPLS_DEBUG */

	if (rti_dst(rti)->sa_len > sizeof(ifra.ifra_x)) {
		log(LOG_INFO, "%s: destination x in fec invalid\n", __func__);
		error = EMSGSIZE;
		goto out;
	}
	
	if (rti_gateway(rti)->sa_family != AF_MPLS) {
		log(LOG_INFO, "%s: segment invalid\n", __func__);
		error = EINVAL;
		goto out;
	}
		
	if (rti_gateway(rti)->sa_len > sizeof(ifra.ifra_seg)) {
		log(LOG_INFO, "%s: segment invalid\n", __func__);
		error = EMSGSIZE;
		goto out;
	}
/*
 * Fetch interface by Forward Equivalence Class (fec).
 */	
 	fec = rtalloc1_fib(rti_dst(rti), 0, 0UL, fibnum);
	if ((fec == NULL) 
		|| (fec->rt_gateway == NULL) 
		|| ((ifp = fec->rt_ifp) == NULL)
		|| (fec->rt_ifa == NULL) 
		|| ((fec->rt_flags & RTF_UP) == 0)) {
		error = ESRCH;
		goto out;
	}
	bzero(&ifra, sizeof(ifra));
	bcopy(rti_dst(rti), &ifra.ifra_x, rti_dst(rti)->sa_len);
	
 	switch ((int)rtm->rtm_type) {
	case RTM_ADD:	
/*
 * Apply MPLS label binding on Forward Equivalence Class (fec).
 */	
		cmd = SIOCAIFADDR;
			
				/* FALLTHROUGH */

	case RTM_DELETE:
/*
 * Delete MPLS label binding on fec.
 */	
		cmd = (cmd == 0) ? SIOCDIFADDR : cmd;
/*
 * Perform MPLS control operations on interface-layer.
 */		
 		bcopy(rti_gateway(rti), &ifra.ifra_seg, rti_gateway(rti)->sa_len);
		ifra.ifra_flags = rti_flags(rti);
 		
 		RT_UNLOCK(fec);
 		error = mpls_control(NULL, cmd, (caddr_t)&ifra, ifp, NULL);
		RT_LOCK(fec); 
		break;
	case RTM_GET: 
/*
 * XXX: looks ugly... I'll delegate this operation 
 * XXX: back to rt_output, but I'm not yet sure, if 
 * XXX: I'll should do that...
 */
		ifra.ifra_seg.sftn_len = SMPLS_LEN;
		ifra.ifra_seg.sftn_family = AF_MPLS;
		
		((struct sockaddr_mpls *)&ifra.ifra_seg)->smpls_label = 
			satosmpls_label(rti_gateway(rti));
/*
 * Fetch Incoming Label Map (ilm) by MPLS label binding on fec.
 */		
		*rt = ((ifra.ifra_flags & RTF_MPE) == 0) 
			? rtalloc1_fib((struct sockaddr *)&ifra.ifra_seg, 
				0, 0UL, ifp->if_fib) : NULL;	
		
		if (*rt != NULL) {
/*
 * Update by socket(2) on route(4) used Service Data Unit (sdu).
 */			
			bcopy(rt_key(*rt), rti_dst(rti), 
				rt_key(*rt)->sa_len); 
			bcopy((*rt)->rt_gateway, rti_gateway(rti), 
				(*rt)->rt_gateway->sa_len);
		} else
		 	error = EADDRNOTAVAIL;
					
		break;
	default:
		log(LOG_INFO, "%s: command invalid\n", __func__);		
		error = EOPNOTSUPP;
		break;
	}	
out:	
	if (fec != NULL) 
		RTFREE_LOCKED(fec);
	
	return (error);
}