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

📄 irlap_frame.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		irlap_send_i_frame(self, tx_skb, RSP_FRAME);	} else {		irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);		self->window -= 1;	}}/* * Function irlap_resend_rejected_frames (nr) * *    Resend frames which has not been acknowledged. Should be safe to *    traverse the list without locking it since this function will only be *    called from interrupt context (BH) */void irlap_resend_rejected_frames(struct irlap_cb *self, int command){	struct sk_buff *tx_skb;	struct sk_buff *skb;	int count;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	/* Initialize variables */	count = skb_queue_len(&self->wx_list);	/*  Resend unacknowledged frame(s) */	skb = skb_peek(&self->wx_list);	while (skb != NULL) {		irlap_wait_min_turn_around(self, &self->qos_tx);		/* We copy the skb to be retransmitted since we will have to		 * modify it. Cloning will confuse packet sniffers		 */		/* tx_skb = skb_clone( skb, GFP_ATOMIC); */		tx_skb = skb_copy(skb, GFP_ATOMIC);		if (!tx_skb) {			IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);			return;		}		/* Clear old Nr field + poll bit */		tx_skb->data[1] &= 0x0f;		/*		 *  Set poll bit on the last frame retransmitted		 */		if (count-- == 1)			tx_skb->data[1] |= PF_BIT; /* Set p/f bit */		else			tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */		irlap_send_i_frame(self, tx_skb, command);		/*		 *  If our skb is the last buffer in the list, then		 *  we are finished, if not, move to the next sk-buffer		 */		if (skb == skb_peek_tail(&self->wx_list))			skb = NULL;		else			skb = skb->next;	}#if 0 /* Not yet */	/*	 *  We can now fill the window with additional data frames	 */	while (!skb_queue_empty(&self->txq)) {		IRDA_DEBUG(0, "%s(), sending additional frames!\n", __FUNCTION__);		if (self->window > 0) {			skb = skb_dequeue( &self->txq);			IRDA_ASSERT(skb != NULL, return;);			/*			 *  If send window > 1 then send frame with pf			 *  bit cleared			 */			if ((self->window > 1) &&			    !skb_queue_empty(&self->txq)) {				irlap_send_data_primary(self, skb);			} else {				irlap_send_data_primary_poll(self, skb);			}			kfree_skb(skb);		}	}#endif}void irlap_resend_rejected_frame(struct irlap_cb *self, int command){	struct sk_buff *tx_skb;	struct sk_buff *skb;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	/*  Resend unacknowledged frame(s) */	skb = skb_peek(&self->wx_list);	if (skb != NULL) {		irlap_wait_min_turn_around(self, &self->qos_tx);		/* We copy the skb to be retransmitted since we will have to		 * modify it. Cloning will confuse packet sniffers		 */		/* tx_skb = skb_clone( skb, GFP_ATOMIC); */		tx_skb = skb_copy(skb, GFP_ATOMIC);		if (!tx_skb) {			IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);			return;		}		/* Clear old Nr field + poll bit */		tx_skb->data[1] &= 0x0f;		/*  Set poll/final bit */		tx_skb->data[1] |= PF_BIT; /* Set p/f bit */		irlap_send_i_frame(self, tx_skb, command);	}}/* * Function irlap_send_ui_frame (self, skb, command) * *    Contruct and transmit an Unnumbered Information (UI) frame * */void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,			 __u8 caddr, int command){	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	IRDA_ASSERT(skb != NULL, return;);	/* Insert connection address */	skb->data[0] = caddr | ((command) ? CMD_FRAME : 0);	irlap_queue_xmit(self, skb);}/* * Function irlap_send_i_frame (skb) * *    Contruct and transmit Information (I) frame */static void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,			       int command){	/* Insert connection address */	skb->data[0] = self->caddr;	skb->data[0] |= (command) ? CMD_FRAME : 0;	/* Insert next to receive (Vr) */	skb->data[1] |= (self->vr << 5);  /* insert nr */	irlap_queue_xmit(self, skb);}/* * Function irlap_recv_i_frame (skb, frame) * *    Receive and parse an I (Information) frame, no harm in making it inline *    since it's called only from one single place (irlap_driver_rcv). */static inline void irlap_recv_i_frame(struct irlap_cb *self,				      struct sk_buff *skb,				      struct irlap_info *info, int command){	info->nr = skb->data[1] >> 5;          /* Next to receive */	info->pf = skb->data[1] & PF_BIT;      /* Final bit */	info->ns = (skb->data[1] >> 1) & 0x07; /* Next to send */	/* Check if this is a command or a response frame */	if (command)		irlap_do_event(self, RECV_I_CMD, skb, info);	else		irlap_do_event(self, RECV_I_RSP, skb, info);}/* * Function irlap_recv_ui_frame (self, skb, info) * *    Receive and parse an Unnumbered Information (UI) frame * */static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,				struct irlap_info *info){	IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);	info->pf = skb->data[1] & PF_BIT;      /* Final bit */	irlap_do_event(self, RECV_UI_FRAME, skb, info);}/* * Function irlap_recv_frmr_frame (skb, frame) * *    Received Frame Reject response. * */static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,				  struct irlap_info *info){	__u8 *frame;	int w, x, y, z;	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	IRDA_ASSERT(skb != NULL, return;);	IRDA_ASSERT(info != NULL, return;);	if (!pskb_may_pull(skb, 4)) {		IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);		return;	}	frame = skb->data;	info->nr = frame[2] >> 5;          /* Next to receive */	info->pf = frame[2] & PF_BIT;      /* Final bit */	info->ns = (frame[2] >> 1) & 0x07; /* Next to send */	w = frame[3] & 0x01;	x = frame[3] & 0x02;	y = frame[3] & 0x04;	z = frame[3] & 0x08;	if (w) {		IRDA_DEBUG(0, "Rejected control field is undefined or not "		      "implemented.\n");	}	if (x) {		IRDA_DEBUG(0, "Rejected control field was invalid because it "		      "contained a non permitted I field.\n");	}	if (y) {		IRDA_DEBUG(0, "Received I field exceeded the maximum negotiated "		      "for the existing connection or exceeded the maximum "		      "this station supports if no connection exists.\n");	}	if (z) {		IRDA_DEBUG(0, "Rejected control field control field contained an "		      "invalid Nr count.\n");	}	irlap_do_event(self, RECV_FRMR_RSP, skb, info);}/* * Function irlap_send_test_frame (self, daddr) * *    Send a test frame response * */void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,			   struct sk_buff *cmd){	struct sk_buff *tx_skb;	struct test_frame *frame;	__u8 *info;	tx_skb = alloc_skb(cmd->len + sizeof(struct test_frame), GFP_ATOMIC);	if (!tx_skb)		return;	/* Broadcast frames must include saddr and daddr fields */	if (caddr == CBROADCAST) {		frame = (struct test_frame *)			skb_put(tx_skb, sizeof(struct test_frame));		/* Insert the swapped addresses */		frame->saddr = cpu_to_le32(self->saddr);		frame->daddr = cpu_to_le32(daddr);	} else		frame = (struct test_frame *) skb_put(tx_skb, LAP_ADDR_HEADER + LAP_CTRL_HEADER);	frame->caddr = caddr;	frame->control = TEST_RSP | PF_BIT;	/* Copy info */	info = skb_put(tx_skb, cmd->len);	memcpy(info, cmd->data, cmd->len);	/* Return to sender */	irlap_wait_min_turn_around(self, &self->qos_tx);	irlap_queue_xmit(self, tx_skb);}/* * Function irlap_recv_test_frame (self, skb) * *    Receive a test frame * */static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,				  struct irlap_info *info, int command){	struct test_frame *frame;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);	if (!pskb_may_pull(skb, sizeof(*frame))) {		IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);		return;	}	frame = (struct test_frame *) skb->data;	/* Broadcast frames must carry saddr and daddr fields */	if (info->caddr == CBROADCAST) {		if (skb->len < sizeof(struct test_frame)) {			IRDA_DEBUG(0, "%s() test frame too short!\n",				   __FUNCTION__);			return;		}		/* Read and swap addresses */		info->daddr = le32_to_cpu(frame->saddr);		info->saddr = le32_to_cpu(frame->daddr);		/* Make sure frame is addressed to us */		if ((info->saddr != self->saddr) &&		    (info->saddr != BROADCAST)) {			return;		}	}	if (command)		irlap_do_event(self, RECV_TEST_CMD, skb, info);	else		irlap_do_event(self, RECV_TEST_RSP, skb, info);}/* * Function irlap_driver_rcv (skb, netdev, ptype) * *    Called when a frame is received. Dispatches the right receive function *    for processing of the frame. * * Note on skb management : * After calling the higher layers of the IrDA stack, we always * kfree() the skb, which drop the reference count (and potentially * destroy it). * If a higher layer of the stack want to keep the skb around (to put * in a queue or pass it to the higher layer), it will need to use * skb_get() to keep a reference on it. This is usually done at the * LMP level in irlmp.c. * Jean II */int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,		     struct packet_type *ptype, struct net_device *orig_dev){	struct irlap_info info;	struct irlap_cb *self;	int command;	__u8 control;	if (dev->nd_net != &init_net)		goto out;	/* FIXME: should we get our own field? */	self = (struct irlap_cb *) dev->atalk_ptr;	/* If the net device is down, then IrLAP is gone! */	if (!self || self->magic != LAP_MAGIC) {		dev_kfree_skb(skb);		return -1;	}	/* We are no longer an "old" protocol, so we need to handle	 * share and non linear skbs. This should never happen, so	 * we don't need to be clever about it. Jean II */	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {		IRDA_ERROR("%s: can't clone shared skb!\n", __FUNCTION__);		dev_kfree_skb(skb);		return -1;	}	/* Check if frame is large enough for parsing */	if (!pskb_may_pull(skb, 2)) {		IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);		dev_kfree_skb(skb);		return -1;	}	command    = skb->data[0] & CMD_FRAME;	info.caddr = skb->data[0] & CBROADCAST;	info.pf      = skb->data[1] &  PF_BIT;	info.control = skb->data[1] & ~PF_BIT; /* Mask away poll/final bit */	control = info.control;	/*  First we check if this frame has a valid connection address */	if ((info.caddr != self->caddr) && (info.caddr != CBROADCAST)) {		IRDA_DEBUG(0, "%s(), wrong connection address!\n",			   __FUNCTION__);		goto out;	}	/*	 *  Optimize for the common case and check if the frame is an	 *  I(nformation) frame. Only I-frames have bit 0 set to 0	 */	if (~control & 0x01) {		irlap_recv_i_frame(self, skb, &info, command);		goto out;	}	/*	 *  We now check is the frame is an S(upervisory) frame. Only	 *  S-frames have bit 0 set to 1 and bit 1 set to 0	 */	if (~control & 0x02) {		/*		 *  Received S(upervisory) frame, check which frame type it is		 *  only the first nibble is of interest		 */		switch (control & 0x0f) {		case RR:			irlap_recv_rr_frame(self, skb, &info, command);			break;		case RNR:			irlap_recv_rnr_frame(self, skb, &info, command);			break;		case REJ:			irlap_recv_rej_frame(self, skb, &info, command);			break;		case SREJ:			irlap_recv_srej_frame(self, skb, &info, command);			break;		default:			IRDA_WARNING("%s: Unknown S-frame %02x received!\n",				__FUNCTION__, info.control);			break;		}		goto out;	}	/*	 *  This must be a C(ontrol) frame	 */	switch (control) {	case XID_RSP:		irlap_recv_discovery_xid_rsp(self, skb, &info);		break;	case XID_CMD:		irlap_recv_discovery_xid_cmd(self, skb, &info);		break;	case SNRM_CMD:		irlap_recv_snrm_cmd(self, skb, &info);		break;	case DM_RSP:		irlap_do_event(self, RECV_DM_RSP, skb, &info);		break;	case DISC_CMD: /* And RD_RSP since they have the same value */		irlap_recv_disc_frame(self, skb, &info, command);		break;	case TEST_CMD:		irlap_recv_test_frame(self, skb, &info, command);		break;	case UA_RSP:		irlap_recv_ua_frame(self, skb, &info);		break;	case FRMR_RSP:		irlap_recv_frmr_frame(self, skb, &info);		break;	case UI_FRAME:		irlap_recv_ui_frame(self, skb, &info);		break;	default:		IRDA_WARNING("%s: Unknown frame %02x received!\n",				__FUNCTION__, info.control);		break;	}out:	/* Always drop our reference on the skb */	dev_kfree_skb(skb);	return 0;}

⌨️ 快捷键说明

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