URL
https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk
Subversion Repositories openrisc_2011-10-31
[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [netinet/] [ip_mroute.c] - Rev 463
Go to most recent revision | Compare with Previous | Blame | View Log
/* * IP multicast forwarding procedures * * Written by David Waitzman, BBN Labs, August 1988. * Modified by Steve Deering, Stanford, February 1989. * Modified by Mark J. Steiglitz, Stanford, May, 1991 * Modified by Van Jacobson, LBL, January 1993 * Modified by Ajit Thyagarajan, PARC, August 1993 * Modified by Bill Fenner, PARC, April 1995 * * MROUTING Revision: 3.5 * $Id: ip_mroute.c,v 1.2 2001-09-27 12:01:55 chris Exp $ */ #include "opt_mrouting.h" #include <sys/param.h> #include <sys/queue.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/protosw.h> #include <sys/errno.h> #include <sys/time.h> #include <sys/kernel.h> #include <sys/ioctl.h> #include <sys/syslog.h> #include <net/if.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/in_pcb.h> #include <netinet/in_var.h> #include <netinet/igmp.h> #include <netinet/igmp_var.h> #include <netinet/ip_mroute.h> #include <netinet/udp.h> #ifndef NTOHL #if BYTE_ORDER != BIG_ENDIAN #define NTOHL(d) ((d) = ntohl((d))) #define NTOHS(d) ((d) = ntohs((u_short)(d))) #define HTONL(d) ((d) = htonl((d))) #define HTONS(d) ((d) = htons((u_short)(d))) #else #define NTOHL(d) #define NTOHS(d) #define HTONL(d) #define HTONS(d) #endif #endif #ifndef MROUTING extern u_long _ip_mcast_src __P((int vifi)); extern int _ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo)); extern int _ip_mrouter_done __P((void)); extern int _ip_mrouter_get __P((int cmd, struct socket *so, struct mbuf **m)); extern int _ip_mrouter_set __P((int cmd, struct socket *so, struct mbuf *m)); extern int _mrt_ioctl __P((int req, caddr_t data, struct proc *p)); /* * Dummy routines and globals used when multicast routing is not compiled in. */ struct socket *ip_mrouter = NULL; /* static u_int ip_mrtproto = 0; */ /* static struct mrtstat mrtstat; */ u_int rsvpdebug = 0; int _ip_mrouter_set(cmd, so, m) int cmd; struct socket *so; struct mbuf *m; { return(EOPNOTSUPP); } int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = _ip_mrouter_set; int _ip_mrouter_get(cmd, so, m) int cmd; struct socket *so; struct mbuf **m; { return(EOPNOTSUPP); } int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = _ip_mrouter_get; int _ip_mrouter_done() { return(0); } int (*ip_mrouter_done)(void) = _ip_mrouter_done; int _ip_mforward(ip, ifp, m, imo) struct ip *ip; struct ifnet *ifp; struct mbuf *m; struct ip_moptions *imo; { return(0); } int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, struct ip_moptions *) = _ip_mforward; int _mrt_ioctl(int req, caddr_t data, struct proc *p) { return EOPNOTSUPP; } int (*mrt_ioctl)(int, caddr_t, struct proc *) = _mrt_ioctl; void rsvp_input(m, iphlen) /* XXX must fixup manually */ struct mbuf *m; int iphlen; { /* 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 (ip_rsvpd != NULL) { if (rsvpdebug) printf("rsvp_input: Sending packet up old-style socket\n"); rip_input(m, iphlen); return; } /* Drop the packet */ m_freem(m); } void ipip_input(struct mbuf *m, int iphlen) { /* XXX must fixup manually */ rip_input(m, iphlen); } int (*legal_vif_num)(int) = 0; /* * This should never be called, since IP_MULTICAST_VIF should fail, but * just in case it does get called, the code a little lower in ip_output * will assign the packet a local address. */ u_long _ip_mcast_src(int vifi) { return INADDR_ANY; } u_long (*ip_mcast_src)(int) = _ip_mcast_src; int ip_rsvp_vif_init(so, m) struct socket *so; struct mbuf *m; { return(EINVAL); } int ip_rsvp_vif_done(so, m) struct socket *so; struct mbuf *m; { return(EINVAL); } void ip_rsvp_force_done(so) struct socket *so; { return; } #else /* MROUTING */ #define M_HASCL(m) ((m)->m_flags & M_EXT) #define INSIZ sizeof(struct in_addr) #define same(a1, a2) \ (bcmp((caddr_t)(a1), (caddr_t)(a2), INSIZ) == 0) #define MT_MRTABLE MT_RTABLE /* since nothing else uses it */ /* * Globals. All but ip_mrouter and ip_mrtproto could be static, * except for netstat or debugging purposes. */ #ifndef MROUTE_LKM struct socket *ip_mrouter = NULL; struct mrtstat mrtstat; int ip_mrtproto = IGMP_DVMRP; /* for netstat only */ #else /* MROUTE_LKM */ extern void X_ipip_input __P((struct mbuf *m, int iphlen)); extern struct mrtstat mrtstat; static int ip_mrtproto; #endif #define NO_RTE_FOUND 0x1 #define RTE_FOUND 0x2 static struct mbuf *mfctable[MFCTBLSIZ]; static u_char nexpire[MFCTBLSIZ]; static struct vif viftable[MAXVIFS]; static u_int mrtdebug = 0; /* debug level */ #define DEBUG_MFC 0x02 #define DEBUG_FORWARD 0x04 #define DEBUG_EXPIRE 0x08 #define DEBUG_XMIT 0x10 static u_int tbfdebug = 0; /* tbf debug level */ static u_int rsvpdebug = 0; /* rsvp debug level */ #define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ #define UPCALL_EXPIRE 6 /* number of timeouts */ /* * Define the token bucket filter structures * tbftable -> each vif has one of these for storing info */ static struct tbf tbftable[MAXVIFS]; #define TBF_REPROCESS (hz / 100) /* 100x / second */ /* * 'Interfaces' associated with decapsulator (so we can tell * packets that went through it from ones that get reflected * by a broken gateway). These interfaces are never linked into * the system ifnet list & no routes point to them. I.e., packets * can't be sent this way. They only exist as a placeholder for * multicast source verification. */ static struct ifnet multicast_decap_if[MAXVIFS]; #define ENCAP_TTL 64 #define ENCAP_PROTO IPPROTO_IPIP /* 4 */ /* prototype IP hdr for encapsulated packets */ static struct ip multicast_encap_iphdr = { #if BYTE_ORDER == LITTLE_ENDIAN sizeof(struct ip) >> 2, IPVERSION, #else IPVERSION, sizeof(struct ip) >> 2, #endif 0, /* tos */ sizeof(struct ip), /* total length */ 0, /* id */ 0, /* frag offset */ ENCAP_TTL, ENCAP_PROTO, 0, /* checksum */ }; /* * Private variables. */ static vifi_t numvifs = 0; static int have_encap_tunnel = 0; /* * one-back cache used by ipip_input to locate a tunnel's vif * given a datagram's src ip address. */ static u_long last_encap_src; static struct vif *last_encap_vif; static u_long X_ip_mcast_src __P((int vifi)); static int X_ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo)); static int X_ip_mrouter_done __P((void)); static int X_ip_mrouter_get __P((int cmd, struct socket *so, struct mbuf **m)); static int X_ip_mrouter_set __P((int cmd, struct socket *so, struct mbuf *m)); static int X_legal_vif_num __P((int vif)); static int X_mrt_ioctl __P((int cmd, caddr_t data)); static int get_sg_cnt(struct sioc_sg_req *); static int get_vif_cnt(struct sioc_vif_req *); static int ip_mrouter_init(struct socket *, struct mbuf *); static int add_vif(struct vifctl *); static int del_vif(vifi_t *); static int add_mfc(struct mfcctl *); static int del_mfc(struct mfcctl *); static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *); static int get_version(struct mbuf *); static int get_assert(struct mbuf *); static int set_assert(int *); static void expire_upcalls(void *); static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t); static void phyint_send(struct ip *, struct vif *, struct mbuf *); static void encap_send(struct ip *, struct vif *, struct mbuf *); static void tbf_control(struct vif *, struct mbuf *, struct ip *, u_long); static void tbf_queue(struct vif *, struct mbuf *); static void tbf_process_q(struct vif *); static void tbf_reprocess_q(void *); static int tbf_dq_sel(struct vif *, struct ip *); static void tbf_send_packet(struct vif *, struct mbuf *); static void tbf_update_tokens(struct vif *); static int priority(struct vif *, struct ip *); void multiencap_decap(struct mbuf *); /* * whether or not special PIM assert processing is enabled. */ static int pim_assert; /* * Rate limit for assert notification messages, in usec */ #define ASSERT_MSG_TIME 3000000 /* * Hash function for a source, group entry */ #define MFCHASH(a, g) MFCHASHMOD(((a) >> 20) ^ ((a) >> 10) ^ (a) ^ \ ((g) >> 20) ^ ((g) >> 10) ^ (g)) /* * Find a route for a given origin IP address and Multicast group address * Type of service parameter to be added in the future!!! */ #define MFCFIND(o, g, rt) { \ register struct mbuf *_mb_rt = mfctable[MFCHASH(o,g)]; \ register struct mfc *_rt = NULL; \ rt = NULL; \ ++mrtstat.mrts_mfc_lookups; \ while (_mb_rt) { \ _rt = mtod(_mb_rt, struct mfc *); \ if ((_rt->mfc_origin.s_addr == o) && \ (_rt->mfc_mcastgrp.s_addr == g) && \ (_mb_rt->m_act == NULL)) { \ rt = _rt; \ break; \ } \ _mb_rt = _mb_rt->m_next; \ } \ if (rt == NULL) { \ ++mrtstat.mrts_mfc_misses; \ } \ } /* * Macros to compute elapsed time efficiently * Borrowed from Van Jacobson's scheduling code */ #define TV_DELTA(a, b, delta) { \ register int xxs; \ \ delta = (a).tv_usec - (b).tv_usec; \ if ((xxs = (a).tv_sec - (b).tv_sec)) { \ switch (xxs) { \ case 2: \ delta += 1000000; \ /* fall through */ \ case 1: \ delta += 1000000; \ break; \ default: \ delta += (1000000 * xxs); \ } \ } \ } #define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \ (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec) #ifdef UPCALL_TIMING u_long upcall_data[51]; static void collate(struct timeval *); #endif /* UPCALL_TIMING */ /* * Handle MRT setsockopt commands to modify the multicast routing tables. */ static int X_ip_mrouter_set(cmd, so, m) int cmd; struct socket *so; struct mbuf *m; { if (cmd != MRT_INIT && so != ip_mrouter) return EACCES; switch (cmd) { case MRT_INIT: return ip_mrouter_init(so, m); case MRT_DONE: return ip_mrouter_done(); case MRT_ADD_VIF: return add_vif (mtod(m, struct vifctl *)); case MRT_DEL_VIF: return del_vif (mtod(m, vifi_t *)); case MRT_ADD_MFC: return add_mfc (mtod(m, struct mfcctl *)); case MRT_DEL_MFC: return del_mfc (mtod(m, struct mfcctl *)); case MRT_ASSERT: return set_assert(mtod(m, int *)); default: return EOPNOTSUPP; } } #ifndef MROUTE_LKM int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = X_ip_mrouter_set; #endif /* * Handle MRT getsockopt commands */ static int X_ip_mrouter_get(cmd, so, m) int cmd; struct socket *so; struct mbuf **m; { struct mbuf *mb; if (so != ip_mrouter) return EACCES; *m = mb = m_get(M_WAIT, MT_SOOPTS); switch (cmd) { case MRT_VERSION: return get_version(mb); case MRT_ASSERT: return get_assert(mb); default: return EOPNOTSUPP; } } #ifndef MROUTE_LKM int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = X_ip_mrouter_get; #endif /* * Handle ioctl commands to obtain information from the cache */ static int X_mrt_ioctl(cmd, data) int cmd; caddr_t data; { int error = 0; switch (cmd) { case (SIOCGETVIFCNT): return (get_vif_cnt((struct sioc_vif_req *)data)); break; case (SIOCGETSGCNT): return (get_sg_cnt((struct sioc_sg_req *)data)); break; default: return (EINVAL); break; } return error; } #ifndef MROUTE_LKM int (*mrt_ioctl)(int, caddr_t) = X_mrt_ioctl; #endif /* * returns the packet, byte, rpf-failure count for the source group provided */ static int get_sg_cnt(req) register struct sioc_sg_req *req; { register struct mfc *rt; int s; s = splnet(); MFCFIND(req->src.s_addr, req->grp.s_addr, rt); splx(s); if (rt != NULL) { req->pktcnt = rt->mfc_pkt_cnt; req->bytecnt = rt->mfc_byte_cnt; req->wrong_if = rt->mfc_wrong_if; } else req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff; return 0; } /* * returns the input and output packet and byte counts on the vif provided */ static int get_vif_cnt(req) register
Go to most recent revision | Compare with Previous | Blame | View Log