Driver/snull/snull_hw_tx()

Last-modified: 2007-09-18 (火) 11:32:29

422 :/*
423 : * Transmit a packet (low level interface)
424 : */
425 :static void snull_hw_tx(char *buf, int len, struct net_device *dev)
426 :{
427 : /*
428 : * This function deals with hw details. This interface loops
429 : * back the packet to the other snull interface (if any).
430 : * In other words, this function implements the snull behaviour,
431 : * while all other procedures are rather device-independent
432 : */
433 : struct iphdr *ih;
434 : struct net_device *dest;
435 : struct snull_priv *priv;
436 : u32 *saddr, *daddr;
437 : struct snull_packet *tx_buffer;
438 :
439 : /* I am paranoid. Ain't I? */
440 : if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {

この時点でbufferはTCP/IPパケットの状態になっているはず→つまりヘッダが設定されている。
長さがethhdr + iphdrということは、パケットの状態が正しくない。

441 : printk("snull: Hmm... packet too short (%i octets)\n",
442 : len);
443 : return;
444 : }
445 :
446 : if (0) { /* enable this conditional to look at the data */

デバッグ用

447 : int i;
448 : PDEBUG("len is %i\n" KERN_DEBUG "data:",len);
449 : for (i=14 ; i<len; i++)
450 : printk(" %02x",buf[i]&0xff);
451 : printk("\n");
452 : }
453 : /*
454 : * Ethhdr is 14 bytes, but the kernel arranges for iphdr
455 : * to be aligned (i.e., ethhdr is unaligned)
456 : */
457 : ih = (struct iphdr *)(buf+sizeof(struct ethhdr));

buf+sizeof(struct ehthdr)がなぜ成り立つのか分からない。
アドレスの計算。ihのアドレスを取得して、iphdrにキャストしてあげれば、構造体を取得できる。

458 : saddr = &ih->saddr;
459 : daddr = &ih->daddr;

ソースアドレスとデスティネーションアドレスをクラスCに変更したい。

460 :
461 : ((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
462 : ((u8 *)daddr)[2] ^= 1;

クラスCに変更。なんで?
本では省略されているためにわかりません。

463 :
464 : ih->check = 0; /* and rebuild the checksum (ip needs it) */
465 : ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);

チェックサムの設定

466 :
467 : if (dev == snull_devs[0])
468 : PDEBUGG("%08x:%05i --> %08x:%05i\n",
469 : ntohl(ih->saddr),ntohs*1->source),
470 : ntohl(ih->daddr),ntohs*2->dest));
471 : else
472 : PDEBUGG("%08x:%05i <-- %08x:%05i\n",
473 : ntohl(ih->daddr),ntohs*3->dest),
474 : ntohl(ih->saddr),ntohs*4->source));
475 :
476 : /*
477 : * Ok, now the packet is ready for transmission: first simulate a
478 : * receive interrupt on the twin device, then a
479 : * transmission-done on the transmitting device
480 : */

↓tx_bufferにすべてコピーするための準備

481 : dest = snull_devs[dev == snull_devs[0] ? 1 : 0];
482 : priv = netdev_priv(dest);
483 : tx_buffer = snull_get_tx_buffer(dev);
484 : tx_buffer->datalen = len;

↑tx_bufferにすべてコピーするための準備

485 : memcpy(tx_buffer->data, buf, len);

tx_bufferにすべてコピー

486 : snull_enqueue_buf(dest, tx_buffer);

待ち列に挿入

487 : if (priv->rx_int_enabled) {
488 : priv->status |= SNULL_RX_INTR;

受信割り込みを有効にする。

489 : snull_interrupt(0, dest, NULL);

割り込みをかけている?

490 : }
491 :
492 : priv = netdev_priv(dev);

デバイスからprivateデータを取得

493 : priv->tx_packetlen = len;
494 : priv->tx_packetdata = buf;
495 : priv->status |= SNULL_TX_INTR;
496 : if (lockup && ((priv->stats.tx_packets + 1) % lockup) == 0) {
497 : /* Simulate a dropped transmit interrupt */
498 : netif_stop_queue(dev);
499 : PDEBUG("Simulate lockup at %ld, txp %ld\n", jiffies,
500 : (unsigned long) priv->stats.tx_packets);
501 : }
502 : else
503 : snull_interrupt(0, dev, NULL);
504 :}


*1 (struct tcphdr *)(ih+1
*2 (struct tcphdr *)(ih+1
*3 (struct tcphdr *)(ih+1
*4 (struct tcphdr *)(ih+1