📄 sdl_udp2.c
字号:
} prv->config.ifflags &= ~SDL_FLAGS_IFRX; sdl->statem.deadr_state = SDL_STATE_IDLE; sdl->state = SDL_DISABLED; return(0);}/* * Trick to link mblks to sk_bufs */static void sdl_udp_freebuf(char *arg){ struct sk_buff *skb = (struct sk_buff *)arg; struct sock *sk = skb->sk; skb_free_datagram(sk, skb);}static mblk_t *sdl_udp_esballoc(struct sk_buff *skb, unsigned char* base, int size){ struct free_rtn f; f.free_func = sdl_udp_freebuf; f.free_arg = (char *)skb; return esballoc(base, size, BRPI_MED, &f);}/* * This is equivalent of RxISR. */static voidsdl_udp_data_ready(struct sock *sk, int bytes){ int err; struct sk_buff *skb; sdl_t *sdl = (sdl_t *)sock->protinfo.destruct_hook; sdl_udpdev_t *prv = sdl->device.priv; int rx_on = ( sdl && sdl->statem.daedr_state == SDL_STATE_IN_SERVICE ); (void)bytes; while ( (skb = skb_recv_datagram(sk, 0, 1, &err)) ) { if ( rx_on ) { mblk_t *mp; caddr_t data = skb->h.raw + sizeof(struct udphdr); size_t len = skb->len + sizeof(struct udphdr); sdl->stats.rx_sus++; sdl->stats.rx_bytes += len; skb->sk = sk; /* just to be sure */ if ( canputq(sdl->rq) && (mp = sdl_udp_allocb(skb, data, len)) ) { putq(sdl->rq, mp); } else { sdl->stats.rx_overruns++; sdl->stats.rx_buffer_overflows++; priv->dcalls.daedr_error_frame(sdl); } } } if ( err && rx_on && abs(err) != EAGAIN ) /* FIXME: analyze this error */ priv->dcalls.daedr_error_frame(sdl); return;}/* * This is equivalent of TxISR. */static intsdl_udp_xmit(sdl_t *sdl, mblk_t *mp){ int n, size, tdiff; mblk_t *db; sdl_device_t *dev = &sdl->device; sdl_udpdev_t *prv = dev->priv; if ( (tdiff = jiffies - prv->timestamp) < 0 ) return EAGAIN; /* throttle */ if ( tdiff > 0 ) { prv->bytecount = 0; prv->timestamp = jiffies; } for ( size=0, n=0, db=mp; db; db=db->b_cont ) if ( db->b_data->db_type == M_DATA && db->b_wptr > db->b_rptr ) { size += db->b_wptr - db->b_rptr; n++; } if ( n ) { int err=0, size; struct msghdr udpmsg; struct iovec iov[n]; for ( n=0, db=mp; db; db=db->b_cont ) { if ( db->b_data->db_type == M_DATA && db->b_wptr > db->b_rptr ) { ioc[n].iov_base = db->b_rptr; iov[n].iov_len = db->b_wptr - db->b_rptr; } } udpmsg.msg_name = (void *)&prv->rem_addr; udpmsg.msg_namelen = sizeof(prv->rem_addr); udpmsg.msg_iov = iov; udpmsg.msg_iovlen = n; udpmsg.msg_control = NULL; udpmsg.msg_controllen = 0; udpmsg.msg_flags = 0; { mm_segment_t fs = get_fs(); set_fs(KERNEL_DS); err = sock_sendmsg(prv->udpsock, &udpmsg, size); set_fs(fs); } if ( err ) { switch ( abs(err) ) { case ENOMEM: /* ran out of memory */ case ENOBUFS: /* ran out of memory */ case EAGAIN: /* no space on non-blocking socket */ case ERESTARTSYS: /* signal */ return EAGAIN; /* temporary, try again later */ case EINVAL: /* bad address */ case EACCES: /* tried to send on broadcast address from nonbroadcast socket */ case ENODEV: /* bad index on iface directed output */ case EFAULT: /* bad user space address */ return abs(err); /* bad error, link unusable */ case EPERM: /* blocked by firewall */ case EMSGSIZE: /* message bigger than MTU */ sdl->stats.tx_sus_in_error++; freemsg(mp); return(0); case EPIPE: /* socket closed */ case ENOTCONN: /* sk->state != TCP_ESTABLISHED connected socket */ case ECONNREFUSED: /* no receiver */ case ENETDOWN: /* couldn't route to destination */ case ENETUNREACH: /* cant route to dest */ case EHOSTUNREACH: /* no routing entry to dest */ return EAGAIN; } freemsg(mp); return(abs(err)); } sdl->stats.tx_bytes += size; sdl->stats.tx_sus++; prv->bytecount += size; while ( prv->bytecount >= prv->tickbytes ) { prv->bytecount -= prv->tickbytes; prv->timestamp++; } } return(0);}/* * -------------------------------------- * * STREAMS OPEN and CLOSE routines * * -------------------------------------- */static sdl_t *sdl_list = NULL;static sdl_config_t sdl_config_default ={ SS7_PVAR_ITUT_96, /* pvar */ SS7_POPT_HSL | SS7_POPT_XSN, /* popt */ 5, /* M */ 4, /* Tin */ 1, /* Tie */ 32, /* T */ 256, /* D */ 16, /* N */ 577169, /* Te */ 144292, /* De */ 9308, /* Ue */ 10 /* t8 */};static sdl_devops_t sdl_device_operations ={ NULL, /* probe */ sdl_udp_open, /* open */ sdl_udp_close, /* close */ sdl_udp_attach, /* attach */ sdl_udp_detach, /* detach */ sdl_udp_enable, /* enable */ sdl_udp_disable, /* disable */ sdl_udp_xmit, /* xmit */ NULL, /* rtnbuf */ sdl_udp_ioctl /* ioctl */};/* * ============================================ * * STREAMS Definitions * * ============================================ */#if 0static struct module_info sdl_minfo ={ SDL_MOD_ID, /* Module ID number */ SDL_MOD_NAME, /* Module name */ SDL_MIN_SDU, /* Min packet size accepted */ SDL_MAX_SDU, /* Max packet size accepted */ SDL_HIWATER, /* Hi water mark */ SDL_LOWATER /* Lo water mark */};static struct qinit sdl_rinit ={ NULL, /* qi_putp */ /* Read put (message from below) */ NULL, /* qi_srvp */ /* Read queue service */ NULL, /* qi_qopen */ /* Each open */ NULL, /* qi_qclose */ /* Last close */ NULL, /* qi_qadmin */ /* Admin (not used) */ &sdl_minfo, /* qi_minfo */ /* Information */ NULL /* qi_mstat */ /* Statistics */}static struct qinit sdl_winit ={ NULL, /* qi_putp */ /* Write put (message from above) */ NULL, /* qi_srvp */ /* Write queue service */ NULL, /* qi_qopen */ /* Each open */ NULL, /* qi_qclose */ /* Last close */ NULL, /* qi_qadmin */ /* Admin (not used) */ &sdl_minfo, /* qi_minfo */ /* Information */ NULL /* qi_mstat */ /* Statistics */};MODULE_STATICstruct streamtab sdl_udp_info ={ sdl_rinit, /* Upper read queue */ sdl_winit, /* Upper write queue */ NULL, /* Lower read queue (not a mux) */ NULL /* Lower write queue (not a mux) */};#endif/* * ======================================================================= * * LiS Module Initialization (For registered driver.) * * ======================================================================= */static int sdl_udp_initialized = 0;void sdl_udp_init(void){ int err; if ( sdl_udp_initialized > 0 ) return; printk(KERN_INFO SDL_BANNER); /* console splash */ sdl_udp_initialized = sdl_register_driver( SDL_C_MAJOR, sdl_udp_info, SDL_N_MINOR, "sdl_udp", &sdl_device_operations); if ( sdl_udp_initialized > 0 ) sdl_udp_major = sdl_udp_initialized; if ( sdl_udp_initialized == 0 ) sdl_udp_initialized = sdl_udp_major;};void sdl_udp_terminate(void){ if ( sdl_udp_initialized <= 0 ) return; sdl_udp_initialized = sdl_unregister_driver(sdl_udp_major);};/* * ======================================================================= * * Kernel Module Initialization (For unregistered driver.) * * ======================================================================= */#ifdef MODULEint init_module(void){ sdl_udp_init(); if ( sdl_udp_initialized < 0 ) return sdl_udp_initialized; return(0);}void cleanup_module(void){ sdl_udp_terminate;};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -