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

📄 netiucv.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
	skb_put(pskb, NETIUCV_HDRLEN);	pskb->dev = dev;	pskb->ip_summed = CHECKSUM_NONE;	pskb->protocol = ntohs(ETH_P_IP);	while (1) {		struct sk_buff *skb;		ll_header *header = (ll_header *)pskb->data;		if (header->next == 0)			break;		skb_pull(pskb, NETIUCV_HDRLEN);		header->next -= offset;		offset += header->next;		header->next -= NETIUCV_HDRLEN;		if (skb_tailroom(pskb) < header->next) {			printk(KERN_WARNING			       "%s: Illegal next field in iucv header: %d > %d\n",			       dev->name, header->next, skb_tailroom(pskb));			return;		}		skb_put(pskb, header->next);		pskb->mac.raw = pskb->data;		skb = dev_alloc_skb(pskb->len);		if (!skb) {			printk(KERN_WARNING			       "%s Out of memory in netiucv_unpack_skb\n",			       dev->name);			privptr->stats.rx_dropped++;			return;		}		memcpy(skb_put(skb, pskb->len), pskb->data, pskb->len);		skb->mac.raw = skb->data;		skb->dev = pskb->dev;		skb->protocol = pskb->protocol;		pskb->ip_summed = CHECKSUM_UNNECESSARY;		netif_rx(skb);		privptr->stats.rx_packets++;		privptr->stats.rx_bytes += skb->len;		skb_pull(pskb, header->next);		skb_put(pskb, NETIUCV_HDRLEN);	}}static voidconn_action_rx(fsm_instance *fi, int event, void *arg){	iucv_event *ev = (iucv_event *)arg;	iucv_connection *conn = ev->conn;	iucv_MessagePending *eib = (iucv_MessagePending *)ev->data;	netiucv_priv *privptr = (netiucv_priv *)conn->netdev->priv;	__u16 msglen = eib->ln1msg2.ipbfln1f;	int rc;#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	if (!conn->netdev) {		/* FRITZ: How to tell iucv LL to drop the msg? */		printk(KERN_WARNING		       "Received data for unlinked connection\n"); 		return;	}	if (msglen > conn->max_buffsize) {		/* FRITZ: How to tell iucv LL to drop the msg? */		privptr->stats.rx_dropped++;		return;	}	conn->rx_buff->data = conn->rx_buff->tail = conn->rx_buff->head;	conn->rx_buff->len = 0;	rc = iucv_receive(conn->pathid, eib->ipmsgid, eib->iptrgcls,			  conn->rx_buff->data, msglen, NULL, NULL, NULL);	if (rc != 0 || msglen < 5) {		privptr->stats.rx_errors++;		return;	}	netiucv_unpack_skb(conn, conn->rx_buff);}static voidconn_action_txdone(fsm_instance *fi, int event, void *arg){	iucv_event *ev = (iucv_event *)arg;	iucv_connection *conn = ev->conn;	iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data;	netiucv_priv *privptr = NULL;			         /* Shut up, gcc! skb is always below 2G. */	struct sk_buff *skb = (struct sk_buff *)(unsigned long)eib->ipmsgtag;	__u32 txbytes = 0;	__u32 txpackets = 0;	__u32 stat_maxcq = 0;	unsigned long saveflags;	ll_header header;#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	fsm_deltimer(&conn->timer);	if (conn && conn->netdev && conn->netdev->priv)		privptr = (netiucv_priv *)conn->netdev->priv;	if (skb) {		if (privptr) {			privptr->stats.tx_packets++;			privptr->stats.tx_bytes +=				(skb->len - NETIUCV_HDRLEN - NETIUCV_HDRLEN);		}		dev_kfree_skb_any(skb);	}	conn->tx_buff->data = conn->tx_buff->tail = conn->tx_buff->head;	conn->tx_buff->len = 0;	spin_lock_irqsave(&conn->collect_lock, saveflags);	while ((skb = skb_dequeue(&conn->collect_queue))) {		header.next = conn->tx_buff->len + skb->len + NETIUCV_HDRLEN;		memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,		       NETIUCV_HDRLEN);		memcpy(skb_put(conn->tx_buff, skb->len), skb->data, skb->len);		txbytes += skb->len;		txpackets++;		stat_maxcq++;		atomic_dec(&skb->users);		dev_kfree_skb_any(skb);	}	if (conn->collect_len > conn->prof.maxmulti)		conn->prof.maxmulti = conn->collect_len;	conn->collect_len = 0;	spin_unlock_irqrestore(&conn->collect_lock, saveflags);	if (conn->tx_buff->len) {		int rc;		header.next = 0;		memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,		       NETIUCV_HDRLEN);		fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,			     CONN_EVENT_TIMER, conn);		conn->prof.send_stamp = xtime;		rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0,			       conn->tx_buff->data, conn->tx_buff->len);		conn->prof.doios_multi++;		conn->prof.txlen += conn->tx_buff->len;		if (rc != 0) {			fsm_deltimer(&conn->timer);			fsm_newstate(fi, CONN_STATE_IDLE);			if (privptr)				privptr->stats.tx_errors += txpackets;		} else {			if (privptr) {				privptr->stats.tx_packets += txpackets;				privptr->stats.tx_bytes += txbytes;			}			if (stat_maxcq > conn->prof.maxcqueue)				conn->prof.maxcqueue = stat_maxcq;		}	} else		fsm_newstate(fi, CONN_STATE_IDLE);}static voidconn_action_connaccept(fsm_instance *fi, int event, void *arg){	iucv_event *ev = (iucv_event *)arg;	iucv_connection *conn = ev->conn;	iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;	net_device *netdev = conn->netdev;	netiucv_priv *privptr = (netiucv_priv *)netdev->priv;	int rc;	__u16 msglimit;	__u8 udata[16];#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	rc = iucv_accept(eib->ippathid, NETIUCV_QUEUELEN_DEFAULT, udata, 0,			 conn->handle, conn, NULL, &msglimit);	if (rc != 0) {		printk(KERN_WARNING		       "%s: IUCV accept failed with error %d\n",		       netdev->name, rc);		return;	}	fsm_newstate(fi, CONN_STATE_IDLE);	conn->pathid = eib->ippathid;	netdev->tx_queue_len = msglimit;	fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);}static voidconn_action_connreject(fsm_instance *fi, int event, void *arg){	iucv_event *ev = (iucv_event *)arg;	// iucv_connection *conn = ev->conn;	iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;	__u8 udata[16];#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	iucv_sever(eib->ippathid, udata);}static voidconn_action_connack(fsm_instance *fi, int event, void *arg){	iucv_event *ev = (iucv_event *)arg;	iucv_connection *conn = ev->conn;	iucv_ConnectionComplete *eib = (iucv_ConnectionComplete *)ev->data;	net_device *netdev = conn->netdev;	netiucv_priv *privptr = (netiucv_priv *)netdev->priv;#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	fsm_newstate(fi, CONN_STATE_IDLE);	conn->pathid = eib->ippathid;	netdev->tx_queue_len = eib->ipmsglim;	fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);}static voidconn_action_connsever(fsm_instance *fi, int event, void *arg){	iucv_event *ev = (iucv_event *)arg;	iucv_connection *conn = ev->conn;	// iucv_ConnectionSevered *eib = (iucv_ConnectionSevered *)ev->data;	net_device *netdev = conn->netdev;	netiucv_priv *privptr = (netiucv_priv *)netdev->priv;	int state = fsm_getstate(fi);#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	switch (state) {		case CONN_STATE_IDLE:		case CONN_STATE_TX:			printk(KERN_INFO "%s: Remote dropped connection\n",			       netdev->name);			if (conn->handle)				iucv_unregister_program(conn->handle);			conn->handle = 0;			fsm_newstate(fi, CONN_STATE_STOPPED);			fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);			break;	}}static voidconn_action_start(fsm_instance *fi, int event, void *arg){	iucv_event *ev = (iucv_event *)arg;	iucv_connection *conn = ev->conn;	int rc;#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	if (conn->handle == 0) {		conn->handle =			iucv_register_program(iucvMagic, conn->userid, mask,					      &netiucv_ops, conn);		fsm_newstate(fi, CONN_STATE_STARTWAIT);		if (conn->handle <= 0) {			fsm_newstate(fi, CONN_STATE_REGERR);			conn->handle = 0;			return;		}#ifdef DEBUG		printk(KERN_DEBUG "%s('%s'): registered successfully\n",		       conn->netdev->name, conn->userid);#endif	}#ifdef DEBUG	printk(KERN_DEBUG "%s('%s'): connecting ...\n",	       conn->netdev->name, conn->userid);#endif	rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,			  conn->userid, iucv_host, 0, NULL, NULL, conn->handle,			  conn);	fsm_newstate(fi, CONN_STATE_SETUPWAIT);	switch (rc) {		case 0:			return;		case 11:			printk(KERN_NOTICE			       "%s: User %s is currently not available.\n",			       conn->netdev->name,			       netiucv_printname(conn->userid));			fsm_newstate(fi, CONN_STATE_STARTWAIT);			return;		case 12:			printk(KERN_NOTICE			       "%s: User %s is currently not ready.\n",			       conn->netdev->name,			       netiucv_printname(conn->userid));			fsm_newstate(fi, CONN_STATE_STARTWAIT);			return;		case 13:			printk(KERN_WARNING			       "%s: Too many IUCV connections.\n",			       conn->netdev->name);			fsm_newstate(fi, CONN_STATE_CONNERR);			break;		case 14:			printk(KERN_WARNING			       "%s: User %s has too many IUCV connections.\n",			       conn->netdev->name,			       netiucv_printname(conn->userid));			fsm_newstate(fi, CONN_STATE_CONNERR);			break;		case 15:			printk(KERN_WARNING			       "%s: No IUCV authorization in CP directory.\n",			       conn->netdev->name);			fsm_newstate(fi, CONN_STATE_CONNERR);			break;		default:			printk(KERN_WARNING			       "%s: iucv_connect returned error %d\n",			       conn->netdev->name, rc);			fsm_newstate(fi, CONN_STATE_CONNERR);			break;	}	iucv_unregister_program(conn->handle);	conn->handle = 0;}static voidnetiucv_purge_skb_queue(struct sk_buff_head *q){	struct sk_buff *skb;	while ((skb = skb_dequeue(q))) {		atomic_dec(&skb->users);		dev_kfree_skb_any(skb);	}}static voidconn_action_stop(fsm_instance *fi, int event, void *arg){	iucv_event *ev = (iucv_event *)arg;	iucv_connection *conn = ev->conn;	net_device *netdev = conn->netdev;	netiucv_priv *privptr = (netiucv_priv *)netdev->priv;#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	fsm_newstate(fi, CONN_STATE_STOPPED);	netiucv_purge_skb_queue(&conn->collect_queue);	if (conn->handle)		iucv_unregister_program(conn->handle);	conn->handle = 0;	fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);}static voidconn_action_inval(fsm_instance *fi, int event, void *arg){	iucv_event *ev = (iucv_event *)arg;	iucv_connection *conn = ev->conn;	net_device *netdev = conn->netdev;	printk(KERN_WARNING	       "%s: Cannot connect without username\n",	       netdev->name);}static const fsm_node conn_fsm[] = {	{ CONN_STATE_INVALID,   CONN_EVENT_START,    conn_action_inval      },	{ CONN_STATE_STOPPED,   CONN_EVENT_START,    conn_action_start      },	{ CONN_STATE_STARTWAIT, CONN_EVENT_START,    conn_action_start      },	{ CONN_STATE_STARTWAIT, CONN_EVENT_STOP,     conn_action_stop       },	{ CONN_STATE_SETUPWAIT, CONN_EVENT_STOP,     conn_action_stop       },	{ CONN_STATE_IDLE,      CONN_EVENT_STOP,     conn_action_stop       },	{ CONN_STATE_TX,        CONN_EVENT_STOP,     conn_action_stop       },	{ CONN_STATE_REGERR,    CONN_EVENT_STOP,     conn_action_stop       },	{ CONN_STATE_CONNERR,   CONN_EVENT_STOP,     conn_action_stop       },	{ CONN_STATE_STOPPED,   CONN_EVENT_CONN_REQ, conn_action_connreject },        { CONN_STATE_STARTWAIT, CONN_EVENT_CONN_REQ, conn_action_connaccept },	{ CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_REQ, conn_action_connaccept },	{ CONN_STATE_IDLE,      CONN_EVENT_CONN_REQ, conn_action_connreject },	{ CONN_STATE_TX,        CONN_EVENT_CONN_REQ, conn_action_connreject },	{ CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_ACK, conn_action_connack    },	{ CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_REJ, conn_action_connsever  },	{ CONN_STATE_IDLE,      CONN_EVENT_CONN_REJ, conn_action_connsever  },	{ CONN_STATE_TX,        CONN_EVENT_CONN_REJ, conn_action_connsever  },	{ CONN_STATE_IDLE,      CONN_EVENT_RX,       conn_action_rx         },	{ CONN_STATE_TX,        CONN_EVENT_RX,       conn_action_rx         },	{ CONN_STATE_TX,        CONN_EVENT_TXDONE,   conn_action_txdone     },};static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);/** * Actions for interface - statemachine. *****************************************************************************//** * Startup connection by sending CONN_EVENT_START to it. * * @param fi    An instance of an interface statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from net_device * upon call. */static voiddev_action_start(fsm_instance *fi, int event, void *arg){	net_device   *dev = (net_device *)arg;	netiucv_priv *privptr = dev->priv;	iucv_event   ev;#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	ev.conn = privptr->conn;	fsm_newstate(fi, DEV_STATE_STARTWAIT);	fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);}/** * Shutdown connection by sending CONN_EVENT_STOP to it. * * @param fi    An instance of an interface statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from net_device * upon call. */static voiddev_action_stop(fsm_instance *fi, int event, void *arg){	net_device   *dev = (net_device *)arg;	netiucv_priv *privptr = dev->priv;	iucv_event   ev;#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	ev.conn = privptr->conn;	fsm_newstate(fi, DEV_STATE_STOPWAIT);	fsm_event(privptr->conn->fsm, CONN_EVENT_STOP, &ev);}/** * Called from connection statemachine * when a connection is up and running. * * @param fi    An instance of an interface statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from net_device * upon call. */static voiddev_action_connup(fsm_instance *fi, int event, void *arg){	net_device   *dev = (net_device *)arg;#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	switch (fsm_getstate(fi)) {		case DEV_STATE_STARTWAIT:			fsm_newstate(fi, DEV_STATE_RUNNING);			printk(KERN_INFO			       "%s: connected with remote side\n",			       dev->name);			break;		case DEV_STATE_STOPWAIT:			printk(KERN_INFO			       "%s: got connection UP event during shutdown!!\n",			       dev->name);			break;	}}/** * Called from connection statemachine * when a connection has been shutdown. * * @param fi    An instance of an interface statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from net_device * upon call. */static voiddev_action_conndown(fsm_instance *fi, int event, void *arg){	net_device   *dev = (net_device *)arg;	netiucv_priv *privptr = dev->priv;	iucv_event   ev;#ifdef DEBUG	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);#endif	switch (fsm_getstate(fi)) {		case DEV_STATE_RUNNING:			fsm_newstate(fi, DEV_STATE_STARTWAIT);			ev.conn = privptr->conn;			fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);			break;		case DEV_STATE_STARTWAIT:			break;		case DEV_STATE_STOPWAIT:			fsm_newstate(fi, DEV_STATE_STOPPED);			break;	}}static const fsm_node dev_fsm[] = {	{ DEV_STATE_STOPPED,   DEV_EVENT_START,   dev_action_start    },	{ DEV_STATE_STOPWAIT,  DEV_EVENT_START,   dev_action_start    },	{ DEV_STATE_STOPWAIT,  DEV_EVENT_CONDOWN, dev_action_conndown },	{ DEV_STATE_STARTWAIT, DEV_EVENT_STOP,    dev_action_stop     },	{ DEV_STATE_STARTWAIT, DEV_EVENT_CONUP,   dev_action_connup   },	{ DEV_STATE_STARTWAIT, DEV_EVENT_CONDOWN, dev_action_conndown },	{ DEV_STATE_RUNNING,   DEV_EVENT_STOP,    dev_action_stop     },	{ DEV_STATE_RUNNING,   DEV_EVENT_CONDOWN, dev_action_conndown },	{ DEV_STATE_RUNNING,   DEV_EVENT_CONUP,   fsm_action_nop      },};static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node);

⌨️ 快捷键说明

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