📄 irlap_frame.c
字号:
static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self, struct sk_buff *skb, struct irlap_info *info){ struct xid_frame *xid; discovery_t *discovery = NULL; __u8 *discovery_info; char *text; if (!pskb_may_pull(skb, sizeof(struct xid_frame))) { IRDA_ERROR("%s: frame too short!\n", __FUNCTION__); return; } xid = (struct xid_frame *) skb->data; info->daddr = le32_to_cpu(xid->saddr); info->saddr = le32_to_cpu(xid->daddr); /* Make sure frame is addressed to us */ if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) { IRDA_DEBUG(0, "%s(), frame is not addressed to us!\n", __FUNCTION__); return; } switch (xid->flags & 0x03) { case 0x00: info->S = 1; break; case 0x01: info->S = 6; break; case 0x02: info->S = 8; break; case 0x03: info->S = 16; break; default: /* Error!! */ return; } info->s = xid->slotnr; discovery_info = skb_pull(skb, sizeof(struct xid_frame)); /* * Check if last frame */ if (info->s == 0xff) { /* Check if things are sane at this point... */ if((discovery_info == NULL) || !pskb_may_pull(skb, 3)) { IRDA_ERROR("%s: discovery frame too short!\n", __FUNCTION__); return; } /* * We now have some discovery info to deliver! */ discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC); if (!discovery) { IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__); return; } discovery->data.daddr = info->daddr; discovery->data.saddr = self->saddr; discovery->timestamp = jiffies; discovery->data.hints[0] = discovery_info[0]; if (discovery_info[0] & HINT_EXTENSION) { discovery->data.hints[1] = discovery_info[1]; discovery->data.charset = discovery_info[2]; text = (char *) &discovery_info[3]; } else { discovery->data.hints[1] = 0; discovery->data.charset = discovery_info[1]; text = (char *) &discovery_info[2]; } /* * Terminate string, should be safe since this is where the * FCS bytes resides. */ skb->data[skb->len] = '\0'; strncpy(discovery->data.info, text, NICKNAME_MAX_LEN); discovery->name_len = strlen(discovery->data.info); info->discovery = discovery; } else info->discovery = NULL; irlap_do_event(self, RECV_DISCOVERY_XID_CMD, skb, info);}/* * Function irlap_send_rr_frame (self, command) * * Build and transmit RR (Receive Ready) frame. Notice that it is currently * only possible to send RR frames with the poll bit set. */void irlap_send_rr_frame(struct irlap_cb *self, int command){ struct sk_buff *tx_skb; struct rr_frame *frame; tx_skb = alloc_skb(sizeof(struct rr_frame), GFP_ATOMIC); if (!tx_skb) return; frame = (struct rr_frame *)skb_put(tx_skb, 2); frame->caddr = self->caddr; frame->caddr |= (command) ? CMD_FRAME : 0; frame->control = RR | PF_BIT | (self->vr << 5); irlap_queue_xmit(self, tx_skb);}/* * Function irlap_send_rd_frame (self) * * Request disconnect. Used by a secondary station to request the * disconnection of the link. */void irlap_send_rd_frame(struct irlap_cb *self){ struct sk_buff *tx_skb; struct rd_frame *frame; tx_skb = alloc_skb(sizeof(struct rd_frame), GFP_ATOMIC); if (!tx_skb) return; frame = (struct rd_frame *)skb_put(tx_skb, 2); frame->caddr = self->caddr; frame->caddr = RD_RSP | PF_BIT; irlap_queue_xmit(self, tx_skb);}/* * Function irlap_recv_rr_frame (skb, info) * * Received RR (Receive Ready) frame from peer station, no harm in * making it inline since its called only from one single place * (irlap_driver_rcv). */static inline void irlap_recv_rr_frame(struct irlap_cb *self, struct sk_buff *skb, struct irlap_info *info, int command){ info->nr = skb->data[1] >> 5; /* Check if this is a command or a response frame */ if (command) irlap_do_event(self, RECV_RR_CMD, skb, info); else irlap_do_event(self, RECV_RR_RSP, skb, info);}/* * Function irlap_recv_rnr_frame (self, skb, info) * * Received RNR (Receive Not Ready) frame from peer station * */static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb, struct irlap_info *info, int command){ info->nr = skb->data[1] >> 5; IRDA_DEBUG(4, "%s(), nr=%d, %ld\n", __FUNCTION__, info->nr, jiffies); if (command) irlap_do_event(self, RECV_RNR_CMD, skb, info); else irlap_do_event(self, RECV_RNR_RSP, skb, info);}static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb, struct irlap_info *info, int command){ IRDA_DEBUG(0, "%s()\n", __FUNCTION__); info->nr = skb->data[1] >> 5; /* Check if this is a command or a response frame */ if (command) irlap_do_event(self, RECV_REJ_CMD, skb, info); else irlap_do_event(self, RECV_REJ_RSP, skb, info);}static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb, struct irlap_info *info, int command){ IRDA_DEBUG(0, "%s()\n", __FUNCTION__); info->nr = skb->data[1] >> 5; /* Check if this is a command or a response frame */ if (command) irlap_do_event(self, RECV_SREJ_CMD, skb, info); else irlap_do_event(self, RECV_SREJ_RSP, skb, info);}static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb, struct irlap_info *info, int command){ IRDA_DEBUG(2, "%s()\n", __FUNCTION__); /* Check if this is a command or a response frame */ if (command) irlap_do_event(self, RECV_DISC_CMD, skb, info); else irlap_do_event(self, RECV_RD_RSP, skb, info);}/* * Function irlap_recv_ua_frame (skb, frame) * * Received UA (Unnumbered Acknowledgement) frame * */static inline void irlap_recv_ua_frame(struct irlap_cb *self, struct sk_buff *skb, struct irlap_info *info){ irlap_do_event(self, RECV_UA_RSP, skb, info);}/* * Function irlap_send_data_primary(self, skb) * * Send I-frames as the primary station but without the poll bit set * */void irlap_send_data_primary(struct irlap_cb *self, struct sk_buff *skb){ struct sk_buff *tx_skb; if (skb->data[1] == I_FRAME) { /* * Insert frame sequence number (Vs) in control field before * inserting into transmit window queue. */ skb->data[1] = I_FRAME | (self->vs << 1); /* * Insert frame in store, in case of retransmissions * Increase skb reference count, see irlap_do_event() */ skb_get(skb); skb_queue_tail(&self->wx_list, skb); /* Copy buffer */ tx_skb = skb_clone(skb, GFP_ATOMIC); if (tx_skb == NULL) { return; } self->vs = (self->vs + 1) % 8; self->ack_required = FALSE; self->window -= 1; irlap_send_i_frame( self, tx_skb, CMD_FRAME); } else { IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__); irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME); self->window -= 1; }}/* * Function irlap_send_data_primary_poll (self, skb) * * Send I(nformation) frame as primary with poll bit set */void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb){ struct sk_buff *tx_skb; int transmission_time; /* Stop P timer */ del_timer(&self->poll_timer); /* Is this reliable or unreliable data? */ if (skb->data[1] == I_FRAME) { /* * Insert frame sequence number (Vs) in control field before * inserting into transmit window queue. */ skb->data[1] = I_FRAME | (self->vs << 1); /* * Insert frame in store, in case of retransmissions * Increase skb reference count, see irlap_do_event() */ skb_get(skb); skb_queue_tail(&self->wx_list, skb); /* Copy buffer */ tx_skb = skb_clone(skb, GFP_ATOMIC); if (tx_skb == NULL) { return; } /* * Set poll bit if necessary. We do this to the copied * skb, since retransmitted need to set or clear the poll * bit depending on when they are sent. */ tx_skb->data[1] |= PF_BIT; self->vs = (self->vs + 1) % 8; self->ack_required = FALSE; irlap_next_state(self, LAP_NRM_P); irlap_send_i_frame(self, tx_skb, CMD_FRAME); } else { IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__); if (self->ack_required) { irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME); irlap_next_state(self, LAP_NRM_P); irlap_send_rr_frame(self, CMD_FRAME); self->ack_required = FALSE; } else { skb->data[1] |= PF_BIT; irlap_next_state(self, LAP_NRM_P); irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME); } } /* How much time we took for transmission of all frames. * We don't know, so let assume we used the full window. Jean II */ transmission_time = self->final_timeout; /* Reset parameter so that we can fill next window */ self->window = self->window_size;#ifdef CONFIG_IRDA_DYNAMIC_WINDOW /* Remove what we have not used. Just do a prorata of the * bytes left in window to window capacity. * See max_line_capacities[][] in qos.c for details. Jean II */ transmission_time -= (self->final_timeout * self->bytes_left / self->line_capacity); IRDA_DEBUG(4, "%s() adjusting transmission_time : ft=%d, bl=%d, lc=%d -> tt=%d\n", __FUNCTION__, self->final_timeout, self->bytes_left, self->line_capacity, transmission_time); /* We are allowed to transmit a maximum number of bytes again. */ self->bytes_left = self->line_capacity;#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ /* * The network layer has a intermediate buffer between IrLAP * and the IrDA driver which can contain 8 frames. So, even * though IrLAP is currently sending the *last* frame of the * tx-window, the driver most likely has only just started * sending the *first* frame of the same tx-window. * I.e. we are always at the very begining of or Tx window. * Now, we are supposed to set the final timer from the end * of our tx-window to let the other peer reply. So, we need * to add extra time to compensate for the fact that we * are really at the start of tx-window, otherwise the final timer * might expire before he can answer... * Jean II */ irlap_start_final_timer(self, self->final_timeout + transmission_time); /* * The clever amongst you might ask why we do this adjustement * only here, and not in all the other cases in irlap_event.c. * In all those other case, we only send a very short management * frame (few bytes), so the adjustement would be lost in the * noise... * The exception of course is irlap_resend_rejected_frame(). * Jean II */}/* * Function irlap_send_data_secondary_final (self, skb) * * Send I(nformation) frame as secondary with final bit set * */void irlap_send_data_secondary_final(struct irlap_cb *self, struct sk_buff *skb){ struct sk_buff *tx_skb = NULL; IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == LAP_MAGIC, return;); IRDA_ASSERT(skb != NULL, return;); /* Is this reliable or unreliable data? */ if (skb->data[1] == I_FRAME) { /* * Insert frame sequence number (Vs) in control field before * inserting into transmit window queue. */ skb->data[1] = I_FRAME | (self->vs << 1); /* * Insert frame in store, in case of retransmissions * Increase skb reference count, see irlap_do_event() */ skb_get(skb); skb_queue_tail(&self->wx_list, skb); tx_skb = skb_clone(skb, GFP_ATOMIC); if (tx_skb == NULL) { return; } tx_skb->data[1] |= PF_BIT; self->vs = (self->vs + 1) % 8; self->ack_required = FALSE; irlap_send_i_frame(self, tx_skb, RSP_FRAME); } else { if (self->ack_required) { irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME); irlap_send_rr_frame(self, RSP_FRAME); self->ack_required = FALSE; } else { skb->data[1] |= PF_BIT; irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME); } } self->window = self->window_size;#ifdef CONFIG_IRDA_DYNAMIC_WINDOW /* We are allowed to transmit a maximum number of bytes again. */ self->bytes_left = self->line_capacity;#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ irlap_start_wd_timer(self, self->wd_timeout);}/* * Function irlap_send_data_secondary (self, skb) * * Send I(nformation) frame as secondary without final bit set * */void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb){ struct sk_buff *tx_skb = NULL; /* Is this reliable or unreliable data? */ if (skb->data[1] == I_FRAME) { /* * Insert frame sequence number (Vs) in control field before * inserting into transmit window queue. */ skb->data[1] = I_FRAME | (self->vs << 1); /* * Insert frame in store, in case of retransmissions * Increase skb reference count, see irlap_do_event() */ skb_get(skb); skb_queue_tail(&self->wx_list, skb); tx_skb = skb_clone(skb, GFP_ATOMIC); if (tx_skb == NULL) { return; } self->vs = (self->vs + 1) % 8; self->ack_required = FALSE; self->window -= 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -