⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip_mroute.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 4 页
字号:
	return;    }    tbf_update_tokens(vifp);    /* if there are enough tokens,      * and the queue is empty,     * send this packet out     */    if (t->tbf_q_len == 0) {	/* queue empty, send packet if enough tokens */	if (p_len <= t->tbf_n_tok) {	    t->tbf_n_tok -= p_len;	    tbf_send_packet(vifp, m);	} else {	    /* queue packet and timeout till later */	    tbf_queue(vifp, m);	    timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS);	}    } else if (t->tbf_q_len < t->tbf_max_q_len) {	/* finite queue length, so queue pkts and process queue */	tbf_queue(vifp, m);	tbf_process_q(vifp);    } else {	/* queue length too much, try to dq and queue and process */	if (!tbf_dq_sel(vifp, ip)) {	    mrtstat.mrts_q_overflow++;	    m_freem(m);	    return;	} else {	    tbf_queue(vifp, m);	    tbf_process_q(vifp);	}    }    return;}/*  * adds a packet to the queue at the interface */static voidtbf_queue(vifp, m) 	register struct vif *vifp;	register struct mbuf *m;{    register int s = splnet();    register struct tbf *t = vifp->v_tbf;    if (t->tbf_t == NULL) {	/* Queue was empty */	t->tbf_q = m;    } else {	/* Insert at tail */	t->tbf_t->m_act = m;    }    /* Set new tail pointer */    t->tbf_t = m;#ifdef DIAGNOSTIC    /* Make sure we didn't get fed a bogus mbuf */    if (m->m_act)	panic("tbf_queue: m_act");#endif    m->m_act = NULL;    t->tbf_q_len++;    splx(s);}/*  * processes the queue at the interface */static voidtbf_process_q(vifp)    register struct vif *vifp;{    register struct mbuf *m;    register int len;    register int s = splnet();    register struct tbf *t = vifp->v_tbf;    /* loop through the queue at the interface and send as many packets     * as possible     */    while (t->tbf_q_len > 0) {	m = t->tbf_q;	len = mtod(m, struct ip *)->ip_len;	/* determine if the packet can be sent */	if (len <= t->tbf_n_tok) {	    /* if so,	     * reduce no of tokens, dequeue the packet,	     * send the packet.	     */	    t->tbf_n_tok -= len;	    t->tbf_q = m->m_act;	    if (--t->tbf_q_len == 0)		t->tbf_t = NULL;	    m->m_act = NULL;	    tbf_send_packet(vifp, m);	} else break;    }    splx(s);}static voidtbf_reprocess_q(xvifp)	void *xvifp;{    register struct vif *vifp = xvifp;    if (ip_mrouter == NULL) 	return;    tbf_update_tokens(vifp);    tbf_process_q(vifp);    if (vifp->v_tbf->tbf_q_len)	timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS);}/* function that will selectively discard a member of the queue * based on the precedence value and the priority */static inttbf_dq_sel(vifp, ip)    register struct vif *vifp;    register struct ip *ip;{    register int s = splnet();    register u_int p;    register struct mbuf *m, *last;    register struct mbuf **np;    register struct tbf *t = vifp->v_tbf;    p = priority(vifp, ip);    np = &t->tbf_q;    last = NULL;    while ((m = *np) != NULL) {	if (p > priority(vifp, mtod(m, struct ip *))) {	    *np = m->m_act;	    /* If we're removing the last packet, fix the tail pointer */	    if (m == t->tbf_t)		t->tbf_t = last;	    m_freem(m);	    /* it's impossible for the queue to be empty, but	     * we check anyway. */	    if (--t->tbf_q_len == 0)		t->tbf_t = NULL;	    splx(s);	    mrtstat.mrts_drop_sel++;	    return(1);	}	np = &m->m_act;	last = m;    }    splx(s);    return(0);}static voidtbf_send_packet(vifp, m)    register struct vif *vifp;    register struct mbuf *m;{    struct ip_moptions imo;    int error;    static struct route ro;    int s = splnet();    if (vifp->v_flags & VIFF_TUNNEL) {	/* If tunnel options */	ip_output(m, (struct mbuf *)0, &vifp->v_route,		  IP_FORWARDING, (struct ip_moptions *)0);    } else {	imo.imo_multicast_ifp  = vifp->v_ifp;	imo.imo_multicast_ttl  = mtod(m, struct ip *)->ip_ttl - 1;	imo.imo_multicast_loop = 1;	imo.imo_multicast_vif  = -1;	/*	 * Re-entrancy should not be a problem here, because	 * the packets that we send out and are looped back at us	 * should get rejected because they appear to come from	 * the loopback interface, thus preventing looping.	 */	error = ip_output(m, (struct mbuf *)0, &ro,			  IP_FORWARDING, &imo);	if (mrtdebug & DEBUG_XMIT)	    log(LOG_DEBUG, "phyint_send on vif %d err %d\n", 		vifp - viftable, error);    }    splx(s);}/* determine the current time and then * the elapsed time (between the last time and time now) * in milliseconds & update the no. of tokens in the bucket */static voidtbf_update_tokens(vifp)    register struct vif *vifp;{    struct timeval tp;    register u_long tm;    register int s = splnet();    register struct tbf *t = vifp->v_tbf;    GET_TIME(tp);    TV_DELTA(tp, t->tbf_last_pkt_t, tm);    /*     * This formula is actually     * "time in seconds" * "bytes/second".     *     * (tm / 1000000) * (v_rate_limit * 1000 * (1000/1024) / 8)     *     * The (1000/1024) was introduced in add_vif to optimize     * this divide into a shift.     */    t->tbf_n_tok += tm * vifp->v_rate_limit / 1024 / 8;    t->tbf_last_pkt_t = tp;    if (t->tbf_n_tok > MAX_BKT_SIZE)	t->tbf_n_tok = MAX_BKT_SIZE;    splx(s);}static intpriority(vifp, ip)    register struct vif *vifp;    register struct ip *ip;{    register int prio;    /* temporary hack; may add general packet classifier some day */    /*     * The UDP port space is divided up into four priority ranges:     * [0, 16384)     : unclassified - lowest priority     * [16384, 32768) : audio - highest priority     * [32768, 49152) : whiteboard - medium priority     * [49152, 65536) : video - low priority     */    if (ip->ip_p == IPPROTO_UDP) {	struct udphdr *udp = (struct udphdr *)(((char *)ip) + (ip->ip_hl << 2));	switch (ntohs(udp->uh_dport) & 0xc000) {	    case 0x4000:		prio = 70;		break;	    case 0x8000:		prio = 60;		break;	    case 0xc000:		prio = 55;		break;	    default:		prio = 50;		break;	}	if (tbfdebug > 1)		log(LOG_DEBUG, "port %x prio%d\n", ntohs(udp->uh_dport), prio);    } else {	    prio = 50;    }    return prio;}/* * End of token bucket filter modifications  */intip_rsvp_vif_init(so, m)    struct socket *so;    struct mbuf *m;{    int i;    register int s;    if (rsvpdebug)	printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n",	       so->so_type, so->so_proto->pr_protocol);    if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)	return EOPNOTSUPP;    /* Check mbuf. */    if (m == NULL || m->m_len != sizeof(int)) {	return EINVAL;    }    i = *(mtod(m, int *));     if (rsvpdebug)	printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n",i,rsvp_on);     s = splnet();    /* Check vif. */    if (!legal_vif_num(i)) {	splx(s);	return EADDRNOTAVAIL;    }    /* Check if socket is available. */    if (viftable[i].v_rsvpd != NULL) {	splx(s);	return EADDRINUSE;    }    viftable[i].v_rsvpd = so;    /* This may seem silly, but we need to be sure we don't over-increment     * the RSVP counter, in case something slips up.     */    if (!viftable[i].v_rsvp_on) {	viftable[i].v_rsvp_on = 1;	rsvp_on++;    }    splx(s);    return 0;}intip_rsvp_vif_done(so, m)    struct socket *so;    struct mbuf *m;{	int i;	register int s;     if (rsvpdebug)	printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n",	       so->so_type, so->so_proto->pr_protocol);     if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)	return EOPNOTSUPP;     /* Check mbuf. */    if (m == NULL || m->m_len != sizeof(int)) {	    return EINVAL;    }    i = *(mtod(m, int *));     s = splnet();     /* Check vif. */    if (!legal_vif_num(i)) {	splx(s);        return EADDRNOTAVAIL;    }    if (rsvpdebug)	printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n",	       viftable[i].v_rsvpd, so);    viftable[i].v_rsvpd = NULL;    /* This may seem silly, but we need to be sure we don't over-decrement     * the RSVP counter, in case something slips up.     */    if (viftable[i].v_rsvp_on) {	viftable[i].v_rsvp_on = 0;	rsvp_on--;    }    splx(s);    return 0;}voidip_rsvp_force_done(so)    struct socket *so;{    int vifi;    register int s;    /* Don't bother if it is not the right type of socket. */    if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)	return;    s = splnet();    /* The socket may be attached to more than one vif...this     * is perfectly legal.     */    for (vifi = 0; vifi < numvifs; vifi++) {	if (viftable[vifi].v_rsvpd == so) {	    viftable[vifi].v_rsvpd = NULL;	    /* This may seem silly, but we need to be sure we don't	     * over-decrement the RSVP counter, in case something slips up.	     */	    if (viftable[vifi].v_rsvp_on) {		viftable[vifi].v_rsvp_on = 0;		rsvp_on--;	    }	}    }    splx(s);    return;}voidrsvp_input(m, iphlen)	struct mbuf *m;	int iphlen;{    int vifi;    register struct ip *ip = mtod(m, struct ip *);    static struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET };    register int s;    struct ifnet *ifp;    if (rsvpdebug)	printf("rsvp_input: rsvp_on %d\n",rsvp_on);    /* Can still get packets with rsvp_on = 0 if there is a local member     * of the group to which the RSVP packet is addressed.  But in this     * case we want to throw the packet away.     */    if (!rsvp_on) {	m_freem(m);	return;    }    /* If the old-style non-vif-associated socket is set, then use     * it and ignore the new ones.     */    if (ip_rsvpd != NULL) {	if (rsvpdebug)	    printf("rsvp_input: Sending packet up old-style socket\n");	rip_input(m, iphlen);	return;    }    s = splnet();    if (rsvpdebug)	printf("rsvp_input: check vifs\n");#ifdef DIAGNOSTIC    if (!(m->m_flags & M_PKTHDR))	    panic("rsvp_input no hdr");#endif    ifp = m->m_pkthdr.rcvif;    /* Find which vif the packet arrived on. */    for (vifi = 0; vifi < numvifs; vifi++) {	if (viftable[vifi].v_ifp == ifp) 		break; 	}     if (vifi == numvifs) {	/* Can't find vif packet arrived on. Drop packet. */	if (rsvpdebug)	    printf("rsvp_input: Can't find vif for packet...dropping it.\n");	m_freem(m);	splx(s);	return;    }    if (rsvpdebug)	printf("rsvp_input: check socket\n");    if (viftable[vifi].v_rsvpd == NULL) {	/* drop packet, since there is no specific socket for this	 * interface */	    if (rsvpdebug)		    printf("rsvp_input: No socket defined for vif %d\n",vifi);	    m_freem(m);	    splx(s);	    return;    }    rsvp_src.sin_addr = ip->ip_src;    if (rsvpdebug && m)	printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n",	       m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv)));    if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0)	if (rsvpdebug)	    printf("rsvp_input: Failed to append to socket\n");    else	if (rsvpdebug)	    printf("rsvp_input: send packet up\n");        splx(s);}#ifdef MROUTE_LKM#include <sys/conf.h>#include <sys/exec.h>#include <sys/sysent.h>#include <sys/lkm.h>MOD_MISC("ip_mroute_mod")static intip_mroute_mod_handle(struct lkm_table *lkmtp, int cmd){	int i;	struct lkm_misc	*args = lkmtp->private.lkm_misc;	int err = 0;	switch(cmd) {		static int (*old_ip_mrouter_cmd)();		static int (*old_ip_mrouter_done)();		static int (*old_ip_mforward)();		static int (*old_mrt_ioctl)();		static void (*old_proto4_input)();		static int (*old_legal_vif_num)();		extern struct protosw inetsw[];	case LKM_E_LOAD:		if(lkmexists(lkmtp) || ip_mrtproto)		  return(EEXIST);		old_ip_mrouter_cmd = ip_mrouter_cmd;		ip_mrouter_cmd = X_ip_mrouter_cmd;		old_ip_mrouter_done = ip_mrouter_done;		ip_mrouter_done = X_ip_mrouter_done;		old_ip_mforward = ip_mforward;		ip_mforward = X_ip_mforward;		old_mrt_ioctl = mrt_ioctl;		mrt_ioctl = X_mrt_ioctl;              old_proto4_input = inetsw[ip_protox[ENCAP_PROTO]].pr_input;              inetsw[ip_protox[ENCAP_PROTO]].pr_input = X_ipip_input;		old_legal_vif_num = legal_vif_num;		legal_vif_num = X_legal_vif_num;		ip_mrtproto = IGMP_DVMRP;		printf("\nIP multicast routing loaded\n");		break;	case LKM_E_UNLOAD:		if (ip_mrouter)		  return EINVAL;		ip_mrouter_cmd = old_ip_mrouter_cmd;		ip_mrouter_done = old_ip_mrouter_done;		ip_mforward = old_ip_mforward;		mrt_ioctl = old_mrt_ioctl;              inetsw[ip_protox[ENCAP_PROTO]].pr_input = old_proto4_input;		legal_vif_num = old_legal_vif_num;		ip_mrtproto = 0;		break;	default:		err = EINVAL;		break;	}	return(err);}intip_mroute_mod(struct lkm_table *lkmtp, int cmd, int ver) {	DISPATCH(lkmtp, cmd, ver, ip_mroute_mod_handle, ip_mroute_mod_handle,		 nosys);}#endif /* MROUTE_LKM */#endif /* MROUTING */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -