📄 strip.c
字号:
*ptr++ = hextable[haddr.c[2] & 0xF]; *ptr++ = hextable[haddr.c[3] >> 4]; *ptr++ = hextable[haddr.c[3] & 0xF]; *ptr++ = '-'; *ptr++ = hextable[haddr.c[4] >> 4]; *ptr++ = hextable[haddr.c[4] & 0xF]; *ptr++ = hextable[haddr.c[5] >> 4]; *ptr++ = hextable[haddr.c[5] & 0xF]; *ptr++ = '*'; *ptr++ = key.c[0]; *ptr++ = key.c[1]; *ptr++ = key.c[2]; *ptr++ = key.c[3]; ptr = StuffData(skb->data + sizeof(STRIP_Header), len, ptr, &stuffstate); if (strip_info->firmware_level >= ChecksummedMessages) ptr = add_checksum(buffer+1, ptr); *ptr++ = 0x0D; return(ptr);}static void strip_send(struct strip *strip_info, struct sk_buff *skb){ MetricomAddress haddr; unsigned char *ptr = strip_info->tx_buff; int doreset = (long)jiffies - strip_info->watchdog_doreset >= 0; int doprobe = (long)jiffies - strip_info->watchdog_doprobe >= 0 && !doreset; u32 addr, brd; /* * 1. If we have a packet, encapsulate it and put it in the buffer */ if (skb) { char *newptr = strip_make_packet(ptr, strip_info, skb); strip_info->tx_pps_count++; if (!newptr) strip_info->tx_dropped++; else { ptr = newptr; strip_info->sx_pps_count++; strip_info->tx_packets++; /* Count another successful packet */#ifdef EXT_COUNTERS strip_info->tx_bytes += skb->len; strip_info->tx_rbytes += ptr - strip_info->tx_buff;#endif /*DumpData("Sending:", strip_info, strip_info->tx_buff, ptr);*/ /*HexDump("Sending", strip_info, strip_info->tx_buff, ptr);*/ } } /* * 2. If it is time for another tickle, tack it on, after the packet */ if (doprobe) { StringDescriptor ts = CommandString[strip_info->next_command];#if TICKLE_TIMERS { struct timeval tv; do_gettimeofday(&tv); printk(KERN_INFO "**** Sending tickle string %d at %02d.%06d\n", strip_info->next_command, tv.tv_sec % 100, tv.tv_usec); }#endif if (ptr == strip_info->tx_buff) *ptr++ = 0x0D; *ptr++ = '*'; /* First send "**" to provoke an error message */ *ptr++ = '*'; /* Then add the command */ memcpy(ptr, ts.string, ts.length); /* Add a checksum ? */ if (strip_info->firmware_level < ChecksummedMessages) ptr += ts.length; else ptr = add_checksum(ptr, ptr + ts.length); *ptr++ = 0x0D; /* Terminate the command with a <CR> */ /* Cycle to next periodic command? */ if (strip_info->firmware_level >= StructuredMessages) if (++strip_info->next_command >= ELEMENTS_OF(CommandString)) strip_info->next_command = 0;#ifdef EXT_COUNTERS strip_info->tx_ebytes += ts.length;#endif strip_info->watchdog_doprobe = jiffies + 10 * HZ; strip_info->watchdog_doreset = jiffies + 1 * HZ; /*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev.name);*/ } /* * 3. Set up the strip_info ready to send the data (if any). */ strip_info->tx_head = strip_info->tx_buff; strip_info->tx_left = ptr - strip_info->tx_buff; strip_info->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); /* * 4. Debugging check to make sure we're not overflowing the buffer. */ if (strip_info->tx_size - strip_info->tx_left < 20) printk(KERN_ERR "%s: Sending%5d bytes;%5d bytes free.\n", strip_info->dev.name, strip_info->tx_left, strip_info->tx_size - strip_info->tx_left); /* * 5. If watchdog has expired, reset the radio. Note: if there's data waiting in * the buffer, strip_write_some_more will send it after the reset has finished */ if (doreset) { ResetRadio(strip_info); return; } if (1) { struct in_device *in_dev = in_dev_get(&strip_info->dev); brd = addr = 0; if (in_dev) { read_lock(&in_dev->lock); if (in_dev->ifa_list) { brd = in_dev->ifa_list->ifa_broadcast; addr = in_dev->ifa_list->ifa_local; } read_unlock(&in_dev->lock); in_dev_put(in_dev); } } /* * 6. If it is time for a periodic ARP, queue one up to be sent. * We only do this if: * 1. The radio is working * 2. It's time to send another periodic ARP * 3. We really know what our address is (and it is not manually set to zero) * 4. We have a designated broadcast address configured * If we queue up an ARP packet when we don't have a designated broadcast * address configured, then the packet will just have to be discarded in * strip_make_packet. This is not fatal, but it causes misleading information * to be displayed in tcpdump. tcpdump will report that periodic APRs are * being sent, when in fact they are not, because they are all being dropped * in the strip_make_packet routine. */ if (strip_info->working && (long)jiffies - strip_info->gratuitous_arp >= 0 && memcmp(strip_info->dev.dev_addr, zero_address.c, sizeof(zero_address)) && arp_query(haddr.c, brd, &strip_info->dev)) { /*printk(KERN_INFO "%s: Sending gratuitous ARP with interval %ld\n", strip_info->dev.name, strip_info->arp_interval / HZ);*/ strip_info->gratuitous_arp = jiffies + strip_info->arp_interval; strip_info->arp_interval *= 2; if (strip_info->arp_interval > MaxARPInterval) strip_info->arp_interval = MaxARPInterval; if (addr) arp_send( ARPOP_REPLY, ETH_P_ARP, addr, /* Target address of ARP packet is our address */ &strip_info->dev, /* Device to send packet on */ addr, /* Source IP address this ARP packet comes from */ NULL, /* Destination HW address is NULL (broadcast it) */ strip_info->dev.dev_addr, /* Source HW address is our HW address */ strip_info->dev.dev_addr); /* Target HW address is our HW address (redundant) */ } /* * 7. All ready. Start the transmission */ strip_write_some_more(strip_info->tty);}/* Encapsulate a datagram and kick it into a TTY queue. */static int strip_xmit(struct sk_buff *skb, struct net_device *dev){ struct strip *strip_info = (struct strip *)(dev->priv); if (!netif_running(dev)) { printk(KERN_ERR "%s: xmit call when iface is down\n", dev->name); return(1); } netif_stop_queue(dev); del_timer(&strip_info->idle_timer); /* See if someone has been ifconfigging */ if (strip_info->mtu != strip_info->dev.mtu) strip_changedmtu(strip_info); if (jiffies - strip_info->pps_timer > HZ) { unsigned long t = jiffies - strip_info->pps_timer; unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t/2) / t; unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t/2) / t; unsigned long sx_pps_count = (strip_info->sx_pps_count * HZ * 8 + t/2) / t; strip_info->pps_timer = jiffies; strip_info->rx_pps_count = 0; strip_info->tx_pps_count = 0; strip_info->sx_pps_count = 0; strip_info->rx_average_pps = (strip_info->rx_average_pps + rx_pps_count + 1) / 2; strip_info->tx_average_pps = (strip_info->tx_average_pps + tx_pps_count + 1) / 2; strip_info->sx_average_pps = (strip_info->sx_average_pps + sx_pps_count + 1) / 2; if (rx_pps_count / 8 >= 10) printk(KERN_INFO "%s: WARNING: Receiving %ld packets per second.\n", strip_info->dev.name, rx_pps_count / 8); if (tx_pps_count / 8 >= 10) printk(KERN_INFO "%s: WARNING: Tx %ld packets per second.\n", strip_info->dev.name, tx_pps_count / 8); if (sx_pps_count / 8 >= 10) printk(KERN_INFO "%s: WARNING: Sending %ld packets per second.\n", strip_info->dev.name, sx_pps_count / 8); } strip_send(strip_info, skb); if (skb) dev_kfree_skb(skb); return(0);}/* * IdleTask periodically calls strip_xmit, so even when we have no IP packets * to send for an extended period of time, the watchdog processing still gets * done to ensure that the radio stays in Starmode */static void strip_IdleTask(unsigned long parameter){ strip_xmit(NULL, (struct net_device *)parameter);}/* * Create the MAC header for an arbitrary protocol layer * * saddr!=NULL means use this specific address (n/a for Metricom) * saddr==NULL means use default device source address * daddr!=NULL means use this destination address * daddr==NULL means leave destination address alone * (e.g. unresolved arp -- kernel will call * rebuild_header later to fill in the address) */static int strip_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len){ struct strip *strip_info = (struct strip *)(dev->priv); STRIP_Header *header = (STRIP_Header *)skb_push(skb, sizeof(STRIP_Header)); /*printk(KERN_INFO "%s: strip_header 0x%04X %s\n", dev->name, type, type == ETH_P_IP ? "IP" : type == ETH_P_ARP ? "ARP" : "");*/ header->src_addr = strip_info->true_dev_addr; header->protocol = htons(type); /*HexDump("strip_header", (struct strip *)(dev->priv), skb->data, skb->data + skb->len);*/ if (!daddr) return(-dev->hard_header_len); header->dst_addr = *(MetricomAddress*)daddr; return(dev->hard_header_len);}/* * Rebuild the MAC header. This is called after an ARP * (or in future other address resolution) has completed on this * sk_buff. We now let ARP fill in the other fields. * I think this should return zero if packet is ready to send, * or non-zero if it needs more time to do an address lookup */static int strip_rebuild_header(struct sk_buff *skb){#ifdef CONFIG_INET STRIP_Header *header = (STRIP_Header *) skb->data; /* Arp find returns zero if if knows the address, */ /* or if it doesn't know the address it sends an ARP packet and returns non-zero */ return arp_find(header->dst_addr.c, skb)? 1 : 0;#else return 0;#endif}/************************************************************************//* Receiving routines */static int strip_receive_room(struct tty_struct *tty){ return 0x10000; /* We can handle an infinite amount of data. :-) */}/* * This function parses the response to the ATS300? command, * extracting the radio version and serial number. */static void get_radio_version(struct strip *strip_info, __u8 *ptr, __u8 *end){ __u8 *p, *value_begin, *value_end; int len; /* Determine the beginning of the second line of the payload */ p = ptr; while (p < end && *p != 10) p++; if (p >= end) return; p++; value_begin = p; /* Determine the end of line */ while (p < end && *p != 10) p++; if (p >= end) return; value_end = p; p++; len = value_end - value_begin; len = MIN(len, sizeof(FirmwareVersion) - 1); if (strip_info->firmware_version.c[0] == 0) printk(KERN_INFO "%s: Radio Firmware: %.*s\n", strip_info->dev.name, len, value_begin); sprintf(strip_info->firmware_version.c, "%.*s", len, value_begin); /* Look for the first colon */ while (p < end && *p != ':') p++; if (p >= end) return; /* Skip over the space */ p += 2; len = sizeof(SerialNumber) - 1; if (p + len <= end) { sprintf(strip_info->serial_number.c, "%.*s", len, p); } else { printk(KERN_DEBUG "STRIP: radio serial number shorter (%d) than expected (%d)\n", end - p, len); }}/* * This function parses the response to the ATS325? command, * extracting the radio battery voltage. */static void get_radio_voltage(struct strip *strip_info, __u8 *ptr, __u8 *end){ int len; len = sizeof(BatteryVoltage) - 1; if (ptr + len <= end) { sprintf(strip_info->battery_voltage.c, "%.*s", len, ptr); } else { printk(KERN_DEBUG "STRIP: radio voltage string shorter (%d) than expected (%d)\n", end - ptr, len); }}/* * This function parses the responses to the AT~LA and ATS311 commands, * which list the radio's neighbours. */static void get_radio_neighbours(MetricomNodeTable *table, __u8 *ptr, __u8 *end){ table->num_nodes = 0; while (ptr < end && table->num_nodes < NODE_TABLE_SIZE) { MetricomNode *node = &table->node[table->num_nodes++]; char *dst = node->c, *limit = dst + sizeof(*node) - 1; while (
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -