当前位置:文档之家› 内核协议栈数据包转发完全解析

内核协议栈数据包转发完全解析

内核协议栈数据包转发

目录

1 NAPI流程与非NAPI

1.1NAPI驱动流程

1.2非NAPI流程

1.3NAPI和非NAPI的区别

2内核接受数据

2.1数据接收过程

2.2 采取DMA技术实现

3 e100采用NAPI接收数据过程

3.1 e100_open 启动e100网卡

3.2 e100_rx_alloc_list 建立环形缓冲区

3.3 e100_rx_alloc_skb 分配skb缓存

3.4 e100_poll 轮询函数

3.5 e100_rx_clean 数据包的接收和传输

3.6 e100_rx_indicate

4 队列层

4.1、软中断与下半部

4.2、队列层

5采用非NAPI接收数据过程

5.1netif_rx

5.2轮询与中断调用netif_rx_schedule不同点

5.3 netif_rx_schedule

5.4 net_rx_action

5.5 process_backlog

6数据包进入网络层

6.1 netif_receive_skb():

6.2 ip_rcv():

6.3 ip_rcv_finish():

6.4 dst_input():

6.5本地流程ip_local_deliver:

6.6转发流程ip_forward():

1 NAPI流程与非NAPI

1.1NAPI驱动流程:

中断发生

-->确定中断原因是数据接收完毕(中断原因也可能是发送完毕,DMA完毕,甚至是中断通道上的其他设备中断)

-->通过netif_rx_schedule将驱动自己的napi结构加入softnet_data的poll_list 链表,禁用网卡中断,并发出软中断NET_RX_SOFTIRQ

-->中断返回时触发软中断调用相应的函数net_rx_action,从softnet_data的poll_list

上取下刚挂入的napi结构,并且调用其 poll函数,这个poll函数也是驱动自己提供的,比如e100网卡驱动中的e100_poll等。

-->在poll函数中进行轮询,直到接受完所有的数据或者预算(budget)耗尽。每接收一个报文要分配skb,用eth_type_trans处理并交给netif_receive_skb。

-->如果数据全部接收完(预算没有用完),则重新使能中断并将napi从链表中取下。如果数据没接收完,则什么也不作,等待下一次poll函数被调度。

1.2非NAPI流程:

中断发生

-->确定中断发生的原因是接收完毕。分配skb,读入数据,用eth_type_trans处理并且将skb交给netif_rx

-->在netif_rx中,将packet加入到softnet_data的input_pkt_queue末尾(NAPI 驱动不使用这个 input_pkt_queue),再通过napi_schedule将softnet_data中的backlog(这也是个napi结构)加入 softnet_data的poll_list,最后发出软中断

-->软中断net_rx_action从poll_list上取下softnet_data的backlog,调用其poll 函数,这个poll函数是内核提供的process_backlog

-->函数process_backlog从softnet_data的input_pkt_queue末尾取下skb,并且直接交给netif_receive_skb处理。

-->如果input_pkt_queue中所有skb都处理完则将backlog从队列中除去(注意input_pkt_queue中可能有多个网卡加入的报文,因为它是每cpu公用的)并退出循环;如果预算用完后也跳出循环。最后返回接受到的包数

1.3 NAPI和非NAPI的区别

NAPI和非NAPI的区别

1.NAPI使用中断+轮询的方式,中断产生之后暂时关闭中断然后轮询接收完所有的数据包,接着再开中断。而非NAPI采用纯粹中断的方式,一个中断接收一个数据包

2.NAPI都有自己的struct napi结构,非NAPI没有

3.NAPI有自己的poll函数,而且接收数据都是在软中断调用poll函数时做的,而非NAPI使用公共的process_backlog函数作为其poll函数,接收数据是在硬件中断中做的

4.NAPI在poll函数中接收完数据之后直接把skb发给netif_receive_skb,而非NAPI 在硬件中断中接收了数据通过 netif_rx把skb挂到公共的input_pkt_queue上,最后由软中断调用的process_backlog函数来将其发送给 netif_receive_skb

驱动以及软中断这块对skb仅仅做了以下简单处理:

1.调用skb_reserve预留出2个字节的空间,这是为了让ip首部对齐,因为以太网首部是14字节

2.调用skb_put将tail指向数据末尾

3.调用eth_type_trans进行如下处理:

(1)将skb->dev指向接收设备

(2)将skb->mac_header指向data(此时data就是指向mac起始地址)

(3)调用skb_pull(skb, ETH_HLEN)将skb->data后移14字节指向ip首部

(4)通过比较目的mac地址判断包的类型,并将skb->pkt_type赋值PACKET_BROADCAST或PACKET_MULTICAST或者PACKET_OTHERHOST,因为PACKET_HOST为0,所以是默认值

(5)最后判断协议类型,并返回(大部分情况下直接返回eth首部的protocol字段的值),这个返回值被存在skb->protocol字段中

总结,结束后,skb->data指向ip首部,skb->mac_header指向 mac首部,skb->protocol 储存L3的协议代码,skb->pkt_type已被设置,skb->len等于接收到的报文长度减去eth 首部长度,也就是整个ip报文的总长。其余字段基本上还是默认值。

2 内核接受数据

2.1数据接收过程

内核从网卡接受数据,传统的经典过程:

1、数据到达网卡;

2、网卡产生一个中断给内核;

3、内核使用I/O指令,从网卡I/O区域中去读取数据;

就是大流量的数据来到,网卡会产生大量的中断,内核在中断上下文中,会浪费大量的资源来处理中断本身。这就是no NAPI方式。

no NAPI:mac每收到一个以太网包,都会产生一个接收中断给cpu,即完全靠中断方式来收包,收包缺点是当网络流量很大时,cpu大部分时间都耗在了处理mac的中断。

NAPI:采用中断+ 轮询的方式:mac收到一个包来后会产生接收中断,但是马上关闭。直到收够了netdev_max_backlog个包(默认300),或者收完mac上所有包后,才再打开接收中断。

通过sysctl来修改https://www.doczj.com/doc/0b15033440.html,dev_max_backlog或者通过proc修改/proc/sys/net/core/netdev_max_backlog

2.2 DMA技术实现

从网卡的I/O区域,包括I/O寄存器或I/O内存中去读取数据,这都要CPU去读,也要占用CPU资源,“CPU从I/O区域读,然后把它放到内存(这个内存指的是系统本身的物理内存,跟外设的内存不相干,也叫主内存)中”。Linux使用DMA技术——让网卡直接从主内存之间读写它们的I/O数据,就不关CPU的事。

1、首先,内核在主内存中为收发数据建立一个环形的缓冲队列(通常叫DMA环形缓冲区)。

2、内核将这个缓冲区通过DMA映射,把这个队列交给网卡;

3、网卡收到数据,就直接放进这个环形缓冲区了——也就是直接放进主内存了;然后,向系统产生一个中断;

4、内核收到这个中断,就取消DMA映射,这样,内核就直接从主内存中读取数据;

这一个过程比传统的过程少了不少工作,因为设备直接把数据放进了主内存,不需要CPU的干预,效率提高了.

对应以上4步,来看它的具体实现:

1、分配环形DMA缓冲区

Linux内核中,用skb来描述一个缓存,所谓分配,就是建立一定数量的skb,然后把它们组织成一个双向链表;

2、建立DMA映射

内核通过调用dma_map_single(struct device *dev,void *buffer,size_t size,enum dma_data_direction direction)建立映射关系。

struct device *dev,描述一个设备;

buffer:把哪个地址映射给设备;也就是某一个skb——要映射全部,当然是做一个双向链表的循环即可;

size:缓存大小;

direction:映射方向——谁传给谁:一般来说,是“双向”映射,数据在设备和内存之间双向流动;

对于PCI设备而言(网卡一般是PCI的),通过另一个包裹函数pci_map_single,这样,就把buffer交给设备了!设备可以直接从里边读/取数据。

3、这一步由硬件完成;

4、取消映射

dma_unmap_single,对PCI而言,大多调用它的包裹函数pci_unmap_single,不取消的话,缓存控制权还在设备手里,要调用它,把主动权掌握在CPU手里——因为我们已经接收到数据了,应该由CPU把数据交给上层网络栈;

当然,不取消之前,通常要读一些状态位信息,诸如此类,一般是调用

dma_sync_single_for_cpu()

让CPU在取消映射前,就可以访问DMA缓冲区中的内容。

每个网卡(MAC)都有自己的专用DMA Engine,如上图的TSEC 和e1000 网卡intel82546。

上图中的红色线就是以太网数据流,DMA与DDR打交道需要其他模块的协助,如TSEC,PCI controller。以太网数据在TSEC<-->DDR PCI_Controller<-->DDR 之间的流动,CPU的core是不需要介入的,只有在数据流动结束时(接收完、发送完),DMA Engine才会以外部中断的方式告诉CPU的core

3 e100接收数据过程

3.1 e100_open 启动e100网卡

e100_open(struct net_device *dev),调用e100_up,就是环形缓冲区的建立,这一步,是通过e100_rx_alloc_list函数调用完成的。

3.2e100_rx_alloc_list 建立环形缓冲区

static int e100_rx_alloc_list(struct nic *nic)

{

struct rx *rx;

unsigned int i, count = nic->params.rfds.count;

nic->rx_to_use = nic->rx_to_clean = NULL;

nic->ru_running = RU_UNINITIALIZED;

/*结构struct rx用来描述一个缓冲区节点,这里分配了count个*/

if(!(nic->rxs = kmalloc(sizeof(struct rx) * count, GFP_ATOMIC)))

return -ENOMEM;

memset(nic->rxs, 0, sizeof(struct rx) * count);

/*虽然是连续分配的,不过还是遍历它,建立双向链表,然后为每一个rx的skb指针分员分配空间

skb用来描述内核中的一个数据包,呵呵,说到重点了*/

for(rx = nic->rxs, i = 0; i < count; rx++, i++) {

rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;

rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1;

if(e100_rx_alloc_skb(nic, rx)) { /*分配缓存*/

e100_rx_clean_list(nic);

return -ENOMEM;

}

}

nic->rx_to_use = nic->rx_to_clean = nic->rxs;

nic->ru_running = RU_SUSPENDED;

return 0;

}

3.3e100_rx_alloc_skb 分配skb缓存

static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)

{

/*skb缓存的分配,是通过调用系统函数dev_alloc_skb来完成的,它同内核栈中通常调用alloc_skb的区别在于,它是原子的,所以,通常在中断上下文中使用*/

if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN)))

return -ENOMEM;

/*初始化必要的成员*/

rx->skb->dev = nic->netdev;

skb_reserve(rx->skb, NET_IP_ALIGN);

/*这里在数据区之前,留了一块sizeof(struct rfd) 这么大的空间,该结构的

一个重要作用,用来保存一些状态信息,比如,在接收数据之前,可以先通过

它,来判断是否真有数据到达等,诸如此类*/

memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd));

/*这是最关键的一步,建立DMA映射,把每一个缓冲区rx->skb->data都映射给了设备,缓存区节点

rx利用dma_addr保存了每一次映射的地址,这个地址后面会被用到*/

rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,

RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);

if(pci_dma_mapping_error(rx->dma_addr)) {

dev_kfree_skb_any(rx->skb);

rx->skb = 0;

rx->dma_addr = 0;

return -ENOMEM;

}

/* Link the RFD to end of RFA by linking previous RFD to

* this one, and clearing EL bit of previous. */

if(rx->prev->skb) {

struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;

/*put_unaligned(val,ptr);用到把var放到ptr指针的地方,它能处理处理内存对齐的问题prev_rfd是在缓冲区开始处保存的一点空间,它的link成员,也保存了映射后的地址*/ put_unaligned(cpu_to_le32(rx->dma_addr),

(u32 *)&prev_rfd->link);

wmb();

prev_rfd->command &= ~cpu_to_le16(cb_el);

pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,

sizeof(struct rfd), PCI_DMA_TODEVICE);

}

return 0;

}

e100_rx_alloc_list函数在一个循环中,建立了环形缓冲区,并调用e100_rx_alloc_skb为每个缓冲区分配了空间,并做了DMA映射。这样,我们就可以来看接收数据的过程了。

3.4 e100_poll 轮询函数

中断函数中,调用netif_rx_schedule,表明使用轮询技术,net_rx_action系统会在未来某一时刻,调用设备的poll函数:

static int e100_poll(struct net_device *netdev, int *budget)

{

struct nic *nic = netdev_priv(netdev);

/*

* netdev->quota是当前CPU能够从所有接口中接收数据包的最大数目,budget 是在初始化阶段分配给接口的weight值,轮询函数必须接受二者之间的最小值。表示轮询函数本次要处理的数据包个数。

*/

unsigned int work_to_do = min(netdev->quota, *budget);

unsigned int work_done = 0;

int tx_cleaned;

/*进行数据包的接收和传输*/

e100_rx_clean(nic, &work_done, work_to_do);

tx_cleaned = e100_tx_clean(nic);

/*接收和传输完成后,就退出poll模块,重启中断*/

/* If no Rx and Tx cleanup work was done, exit polling mode. */

if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {

netif_rx_complete(netdev);

e100_enable_irq(nic);

return 0;

}

*budget -= work_done;

netdev->quota -= work_done;

return 1;

}

目前,我们只关心rx,所以,e100_rx_clean函数就成了我们关注的对象,它用来从缓冲队列中接收全部数据(这或许是取名为clean的原因吧!)

3.5 e100_rx_clean 数据包的接收和传输

static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done,

unsigned int work_to_do)

{

struct rx *rx;

int restart_required = 0;

struct rx *rx_to_start = NULL;

/* are we already rnr? then pay attention!!! this ensures that

* the state machine progression never allows a start with a

* partially cleaned list, avoiding a race between hardware

* and rx_to_clean when in NAPI mode */

if(RU_SUSPENDED == nic->ru_running)

restart_required = 1;

/* 函数最重要的工作,就是遍历环形缓冲区,接收数据*/

for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { int err = e100_rx_indicate(nic, rx, work_done, work_to_do);

if(-EAGAIN == err) {

/* hit quota so have more work to do, restart once

* cleanup is complete */

restart_required = 0;

break;

} else if(-ENODA TA == err)

break; /* No more to clean */

}

/* save our starting point as the place we'll restart the receiver */

if(restart_required)

rx_to_start = nic->rx_to_clean;

/* Alloc new skbs to refill list */

for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { if(unlikely(e100_rx_alloc_skb(nic, rx)))

break; /* Better luck next time (see watchdog) */

}

if(restart_required) {

// ack the rnr?

writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);

e100_start_receiver(nic, rx_to_start);

if(work_done)

(*work_done)++;

}

}

3.6 e100_rx_indicate

static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,

unsigned int *work_done, unsigned int work_to_do)

{

struct sk_buff *skb = rx->skb;

struct rfd *rfd = (struct rfd *)skb->data;

u16 rfd_status, actual_size;

if(unlikely(work_done && *work_done >= work_to_do))

return -EAGAIN;

/* 读取数据之前,也就是取消DMA映射之前,需要先读取cb_complete 状态位,

以确定数据是否真的准备好了,并且,rfd的actual_size中,也包含了真实的数据大小

pci_dma_sync_single_for_cpu函数前面已经介绍过,它让CPU在取消DMA映射之前,具备

访问DMA缓存的能力*/

pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr,

sizeof(struct rfd), PCI_DMA_FROMDEVICE);

rfd_status = le16_to_cpu(rfd->status);

DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status);

/* If data isn't ready, nothing to indicate */

if(unlikely(!(rfd_status & cb_complete)))

return -ENODATA;

/* Get actual data size */

actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;

if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))

actual_size = RFD_BUF_LEN - sizeof(struct rfd);

/* 取消映射,因为通过DMA,网卡已经把数据放在了主内存中,这里一取消,也就意味着,

CPU可以处理主内存中的数据了*/

pci_unmap_single(nic->pdev, rx->dma_addr,

RFD_BUF_LEN, PCI_DMA_FROMDEVICE);

/* this allows for a fast restart without re-enabling interrupts */

if(le16_to_cpu(rfd->command) & cb_el)

nic->ru_running = RU_SUSPENDED;

/*正确地设置data指针,因为最前面有一个sizeof(struct rfd)大小区域,跳过它*/

skb_reserve(skb, sizeof(struct rfd));

/*更新skb的tail和len指针,也是就更新接收到这么多数据的长度*/

skb_put(skb, actual_size);

/*设置协议位*/

skb->protocol = eth_type_trans(skb, nic->netdev);

if(unlikely(!(rfd_status & cb_ok))) {

/* Don't indicate if hardware indicates errors */

nic->net_stats.rx_dropped++;

dev_kfree_skb_any(skb);

} else if(actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) {

/* Don't indicate oversized frames */

nic->rx_over_length_errors++;

nic->net_stats.rx_dropped++;

dev_kfree_skb_any(skb);

} else {

/*网卡驱动要做的最后一步,就是统计接收计数器,设置接收时间戳,然后调用netif_receive_skb,

把数据包交给上层协议栈,自己的光荣始命也就完成了*/

nic->net_stats.rx_packets++;

nic->net_stats.rx_bytes += actual_size;

nic->netdev->last_rx = jiffies;

netif_receive_skb(skb);

if(work_done)

(*work_done)++;

}

rx->skb = NULL;

return 0;

}

网卡驱动执行到这里,数据接收的工作,也就处理完成了。但是,使用这一种方法的驱动,省去了网络栈中一个重要的内容,就是“队列层”,让我们来看看,传统中断接收数据包模式下,使用netif_rx函数调用,又会发生什么。

4 队列层

4.1、软中断与下半部

当用中断处理的时候,为了减少中断处理的工作量,比如,一般中断处理时,需要屏蔽其它中断,如果中断处理时间过长,那么其它中断有可能得不到及时处理,也以,有一种机制,就是把“不必马上处理”的工作,推迟一点,让它在中断处理后的某一个时刻得到处理。这就是下半部。

下半部只是一个机制,它在Linux中,有多种实现方式,其中一种对时间要求最严格的实现方式,叫“软中断”,可以使用:open_softirq()来向内核注册一个软中断,然后,在合适的时候,调用raise_softirq_irqoff()触发它。

如果采用中断方式接收数据(这一节就是在说中断方式接收,后面,就不用这种假设了),

同样也需要软中断,可以调用open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);向内核注册一个名为NET_RX_SOFTIR的软中断,net_rx_action是软中断的处理函数。

然后,在驱动中断处理完后的某一个时刻,调用raise_softirq_irqoff(NET_RX_SOFTIRQ);触发它,这样net_rx_action将得到执行。

4.2、队列层

队列层通常指的是在网卡收发数据的时候,需要维护一个缓冲区队列,来缓存可能存在的突发数据,类似于前面的DMA环形缓冲区。

队列层中,包含了一个叫做struct softnet_data:

struct softnet_data

{

/*throttle 用于拥塞控制,当拥塞发生时,throttle将被设置,后续进入的数据包将被丢弃*/

int throttle;

/*netif_rx函数返回的拥塞级别*/

int cng_level;

int avg_blog;

/*softnet_data 结构包含一个指向接收和传输队列的指针,input_pkt_queue成员指向准备传送

给网络层的sk_buffs包链表的首部的指针,这个队列中的包是由netif_rx函数递交的*/

struct sk_buff_head input_pkt_queue;

struct list_head poll_list;

struct net_device *output_queue;

struct sk_buff *completion_queue;

struct net_device backlog_dev; /* Sorry. 8) */

};

内核使用了一个同名的变量softnet_data,它是一个Per-CPU变量,每个CPU都有一个。net/core/dev.c

DECLARE_PER_CPU(struct softnet_data,softnet_data);

[Copy to clipboard]

CODE:

/*

* 网络模块的核心处理模块.

*/

static int __init net_dev_init(void)

{

int i, rc = -ENOMEM;

BUG_ON(!dev_boot_phase);

net_random_init();

if (dev_proc_init()) /*初始化proc文件系统*/

goto out;

if (netdev_sysfs_init()) /*初始化sysfs文件系统*/

goto out;

/*ptype_all和ptype_base是重点,后面会详细分析,它们都是

struct list_head类型变量,这里初始化链表成员*/

INIT_LIST_HEAD(&ptype_all);

for (i = 0; i < 16; i++)

INIT_LIST_HEAD(&ptype_base[i]);

for (i = 0; i < ARRAY_SIZE(dev_name_head); i++)

INIT_HLIST_HEAD(&dev_name_head[i]);

for (i = 0; i < ARRAY_SIZE(dev_index_head); i++)

INIT_HLIST_HEAD(&dev_index_head[i]);

/*

* 初始化包接收队列,这里我们的重点了.

*/

/*遍历每一个CPU,取得它的softnet_data,我们说过,它是一个struct softnet_data 的Per-CPU变量*/

for (i = 0; i < NR_CPUS; i++) {

struct softnet_data *queue;

/*取得第i个CPU的softnet_data,因为队列是包含在它里边的,所以,我会直接说,“取得队列”*/

queue = &per_cpu(softnet_data, i);

/*初始化队列头*/

skb_queue_head_init(&queue->input_pkt_queue);

queue->throttle = 0;

queue->cng_level = 0;

queue->avg_blog = 10; /* arbitrary non-zero */

queue->completion_queue = NULL;

INIT_LIST_HEAD(&queue->poll_list);

set_bit(__LINK_STATE_START, &queue->backlog_dev.state);

queue->backlog_dev.weight = weight_p;

/*这里,队列中backlog_dev设备,它是一个伪网络设备,不对应任何物理设备,它的poll函数,指向了

process_backlog,后面我们会详细分析*/

queue->backlog_dev.poll = process_backlog;

atomic_set(&queue->backlog_dev.refcnt, 1);

}

#ifdef OFFLINE_SAMPLE

samp_timer.expires = jiffies + (10 * HZ);

add_timer(&samp_timer);

#endif

dev_boot_phase = 0;

/*注册收/发软中断*/

open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);

open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);

hotcpu_notifier(dev_cpu_callback, 0);

dst_init();

dev_mcast_init();

rc = 0;

out:

return rc;

}

这样,初始化完成后,在驱动程序中,在中断处理函数中,会调用netif_rx将数据交上来,这与采用轮询技术,有本质的不同:

5采用非NAPI接收数据过程

5.1 netif_rx

int netif_rx(struct sk_buff *skb)

{

int this_cpu;

struct softnet_data *queue;

unsigned long flags;

/* if netpoll wants it, pretend we never saw it */

if (netpoll_rx(skb))

return NET_RX_DROP;

/*接收时间戳未设置,设置之*/

if (!skb->https://www.doczj.com/doc/0b15033440.html,_sec)

net_timestamp(&skb->stamp);

/*

* 这里准备将数据包放入接收队列,需要禁止本地中断,在入队操作完成后,再打开中断.

*/

local_irq_save(flags);

/*获取当前CPU对应的softnet_data变量*/

this_cpu = smp_processor_id();

queue = &__get_cpu_var(softnet_data);

/*接收计数器累加*/

__get_cpu_var(netdev_rx_stat).total++;

/*接收队列是否已满*/

if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {

if (queue->input_pkt_queue.qlen) {

if (queue->throttle) /*拥塞发生了,丢弃数据包*/

goto drop;

/*数据包入队操作*/

enqueue:

dev_hold(skb->dev); /*累加设备引入计数器*/

__skb_queue_tail(&queue->input_pkt_queue, skb); /*将数据包加入接收队列*/

#ifndef OFFLINE_SAMPLE

get_sample_stats(this_cpu);

#endif

local_irq_restore(flags);

return queue->cng_level;

}

/*

* 驱动程序不断地调用net_rx函数,实现接收数据包的入队操作,当qlen == 0时,则进入这段代码,这里,如果已经被设置拥塞标志的话,则清除它,因为这里将要调用软中断,开始将数据包交给上层了,即上层协议的接收函数将执行出队操作,拥塞自然而然也就不存在了。*/

if (queue->throttle)

queue->throttle = 0;

/*

* netif_rx_schedule函数完成两件重要的工作:

* 1、将bakclog_dev设备加入“处理数据包的设备”的链表当中;

* 2、触发软中断函数,进行数据包接收处理;

*/

netif_rx_schedule(&queue->backlog_dev);

goto enqueue;

}

/*前面判断了队列是否已满,如果已满而标志未设置,设置之,并累加拥塞计数器*/

if (!queue->throttle) {

queue->throttle = 1;

__get_cpu_var(netdev_rx_stat).throttled++;

}

/*拥塞发生,累加丢包计数器,释放数据包*/

drop:

__get_cpu_var(netdev_rx_stat).dropped++;

local_irq_restore(flags);

kfree_skb(skb);

return NET_RX_DROP;

}

从这段代码的分析中,我们可以看到,当第一个数据包被接收后,因为qlen==0,所以首先会调用netif_rx_schedule触发软中断,然后利用goto跳转至入队。因为软中断被触发后,将执行出队操作,把数据交往上层处理。而当这个时候,又有数据包进入,即网卡中断产生,因为它的优先级高过软中断,这样,出队操作即被中断,网卡中断程序再将被调用,netif_rx函数又再次被执行,如果队列未满,就入队返回。中断完成后,软中断的执行过程被恢复而继续执行出队——如此生产者/消费者循环不止,生生不息……

5.2轮询与中断netif_rx_schedule不同点

netif_rx调用netif_rx_schedule进一步处理数据包,我们注意到:

1、前面讨论过,采用轮询技术时,同样地,也是调用netif_rx_schedule,把设备自己传递了过去;

2、这里,采用中断方式,传递的是队列中的一个“伪设备”,并且,这个伪设备的poll函数指针,指向了一个叫做process_backlog的函数;

netif_rx_schedule函数完成两件重要的工作:

1、将bakclog_dev设备加入“处理数据包的设备”的链表当中;

2、触发软中断函数,进行数据包接收处理;

这样,我们可以猜想,在软中断函数中,不论是伪设备bakclog_dev,还是真实的设备(如前面讨论过的e100),都会被软中断函数以:dev-poll()的形式调用,对于e100来说,poll 函数的接收过程已经分析了,而对于其它所有没有采用轮询技术的网络设备来说,它们将统统调用process_backlog函数

OK,我想分析到这里,关于中断处理与轮询技术的差异,已经基本分析开了……

netif_rx_schedule进一步调用__netif_rx_schedule:

5.3__netif_rx_schedule

static inline void netif_rx_schedule(struct net_device *dev)

{

if (netif_rx_schedule_prep(dev))

__netif_rx_schedule(dev);

}

/* Add interface to tail of rx poll list. This assumes that _prep has

* already been called and returned 1.

*/

static inline void __netif_rx_schedule(struct net_device *dev)

{

unsigned long flags;

local_irq_save(flags);

dev_hold(dev);

/*伪设备也好,真实的设备也罢,都被加入了队列层的设备列表*/

list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);

if (dev->quota < 0)

dev->quota += dev->weight;

else

dev->quota = dev->weight;

/*触发软中断*/

__raise_softirq_irqoff(NET_RX_SOFTIRQ);

local_irq_restore(flags);

}

5.4 net_rx_action

软中断被触发,注册的net_rx_action函数将被调用:

/*接收的软中断处理函数*/

static void net_rx_action(struct softirq_action *h)

{

struct softnet_data *queue = &__get_cpu_var(softnet_data);

unsigned long start_time = jiffies;

int budget = netdev_max_backlog;

local_irq_disable();

/*

* 遍历队列的设备链表,如前所述,__netif_rx_schedule已经执行了

* list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);

* 设备bakclog_dev已经被添加进来了

*/

while (!list_empty(&queue->poll_list)) {

struct net_device *dev;

if (budget <= 0 || jiffies - start_time > 1)

goto softnet_break;

local_irq_enable();

/*取得链表中的设备*/

dev = list_entry(queue->poll_list.next,

struct net_device, poll_list);

netpoll_poll_lock(dev);

/*调用设备的poll函数,处理接收数据包,这样,采用轮询技术的网卡,它的真实的poll函数将被调用,

这就回到我们上一节讨论的e100_poll函数去了,而对于采用传统中断处理的设备,它们调用的,都将是

bakclog_dev的process_backlog函数*/

if (dev->quota <= 0 || dev->poll(dev, &budget)) {

netpoll_poll_unlock(dev);

/*处理完成后,把设备从设备链表中删除,又重置于末尾*/

local_irq_disable();

list_del(&dev->poll_list);

list_add_tail(&dev->poll_list, &queue->poll_list);

if (dev->quota < 0)

dev->quota += dev->weight;

else

dev->quota = dev->weight;

} else {

netpoll_poll_unlock(dev);

dev_put(dev);

local_irq_disable();

}

}

out:

local_irq_enable();

return;

softnet_break:

__get_cpu_var(netdev_rx_stat).time_squeeze++;

__raise_softirq_irqoff(NET_RX_SOFTIRQ);

goto out;

}

对于dev->poll(dev, &budget)的调用,一个真实的poll函数的例子,我们已经分析过了,

现在来看process_backlog

5.5 process_backlog

static int process_backlog(struct net_device *backlog_dev, int *budget)

{

int work = 0;

int quota = min(backlog_dev->quota, *budget);

struct softnet_data *queue = &__get_cpu_var(softnet_data);

unsigned long start_time = jiffies;

backlog_dev->weight = weight_p;

/*在这个循环中,执行出队操作,把数据从队列中取出来,交给netif_receive_skb,直至队列为空*/

for (;;) {

struct sk_buff *skb;

struct net_device *dev;

local_irq_disable();

skb = __skb_dequeue(&queue->input_pkt_queue);

if (!skb)

goto job_done;

local_irq_enable();

dev = skb->dev;

netif_receive_skb(skb);

dev_put(dev);

work++;

if (work >= quota || jiffies - start_time > 1)

break;

}

backlog_dev->quota -= work;

*budget -= work;

return -1;

/*当队列中的数据包被全部处理后,将执行到这里*/

job_done:

backlog_dev->quota -= work;

*budget -= work;

list_del(&backlog_dev->poll_list);

smp_mb__before_clear_bit();

netif_poll_enable(backlog_dev);

if (queue->throttle)

queue->throttle = 0;

local_irq_enable();

return 0;

}

这个函数重要的工作,就是出队,然后调用netif_receive_skb()将数据包交给上层,这与上一节讨论的poll是一样的。这也是为什么在网卡驱动的编写中,采用中断技术,要调用netif_rx,而采用轮询技术,要调用netif_receive_skb啦!

到了这里,就处理完数据包与设备相关的部分了,数据包将进入上层协议栈……

6 数据进入网络层

计算机网络课程设计---基于Wireshark的网络数据包内容解析

基于Wireshark的网络数据包内容解析 摘要本课程设计是利用抓包软件Wireshark,对网络服务器与客户端进行网络数据收发过程中产生的包进行抓取,然后对所抓取的包进行分析,并结合的协议进行分析,达到了解各种数据包结构的目的。设计过程中对各种包进行抓取分析,各种包之间比较,了解每种包的传输过程与结构,通过本次课程设计,能很好的运用Wireshark对数据包分析和Wireshark各种运用,达到课程设计的目的。 关键词IP协议;TCP协议;UDP协议;ARP协议;Wireshark;计算机网络; 1 引言 本课程设计主要是设计一个基于Wireshark的网络数据包内容解析,抓取数据包,然后对所抓取的包进行分析,并结合的协议进行分析,达到了解各种数据包结构的目的 1.1 课程设计目的 Wireshark是一个网络封包分析软件。可以对网络中各种网络数据包进行抓取,并尽可能显示出最为详细的网络封包资料,计算机网络课程设计是在学习了计算机网络相关理论后,进行综合训练课程,其目的是: 1.了解并会初步使用Wireshark,能在所用电脑上进行抓包; 2.了解IP数据包格式,能应用该软件分析数据包格式。 1.2 课程设计要求 (1)按要求编写课程设计报告书,能正确阐述设计结果。 (2)通过课程设计培养学生严谨的科学态度,认真的工作作风和团队协作精神。 (3)学会文献检索的基本方法和综合运用文献的能力。

(4)在老师的指导下,要求每个学生独立完成课程设计的全部内容。 1.3 课程设计背景 一、Wireshark(前称Ethereal)是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料。 网络封包分析软件的功能可想像成 "电工技师使用电表来量测电流、电压、电阻" 的工作 - 只是将场景移植到网络上,并将电线替换成网络线。在过去,网络封包分析软件是非常昂贵,或是专门属于营利用的软件。Wireshark的出现改变了这一切。在GNUGPL通用许可证的保障范围底下,使用者可以以免费的代价取得软件与其源代码,并拥有针对其源代码修改及客制化的权利。Wireshark是目前全世界最广泛的网络封包分析软件之一。 二、网络嗅探需要用到网络嗅探器,其最早是为网络管理人员配备的工具,有了嗅探器网络管理员可以随时掌握网络的实际情况,查找网络漏洞和检测网络性能,当网络性能急剧下降的时候,可以通过嗅探器分析网络流量,找出网络阻塞的来源。网络嗅探是网络监控系统的实现基础。 网络嗅探需要用到网络嗅探器,其最早是为网络管理人员配备的工具,有了嗅探器网络管理员可以随时掌握网络的实际情况,查找网络漏洞和检测网络性能,当网络性能急剧下降的时候,可以通过嗅探器分析网络流量,找出网络阻塞的来源。嗅探器也是很多程序人员在编写网络程序时抓包测试的工具,因为我们知道网络程序都是以数据包的形式在网络中进行传输的,因此难免有协议头定义不对的。 网络嗅探的基础是数据捕获,网络嗅探系统是并接在网络中来实现对于数据的捕获的,这种方式和入侵检测系统相同,因此被称为网络嗅探。网络嗅探是网络监控系统的实现基础,首先就来详细地介绍一下网络嗅探技术,接下来就其在网络监控系统的运用进行阐述。 2 网络协议基础知识 2.1 IP协议 (1) IP协议介绍

网络数据包的捕获与分析毕业设计

网络数据包的捕获与分析 【摘要】网络数据包的捕获对于网络安全有着巨大的作用,为我们更好的分析网络中的数据流提供了帮助。本论文是基于Windows下开发一个网络监听工具,侧重点在于实现网络数据包的捕获,然后分析并显示捕获到的数据包信息这部分功能的实现,如分析:IP首部协议类型、源IP、目的IP和端口号等。采用的是Winpcap(Windows Packet Capture)来实现的抓包功能。通过VC++6.0中MFC编程实现通过一个完整界面来控制调用Winpcap中的函数来实现对网卡信息的捕获和循环捕获数据包,然后通过预先对于IP、TCP、UDP等数据包的定义和TCP/IP等协议来解析其中包含的内容并返回显示捕获到数据包的信息,当然也可以保存捕获到的数据包到指定地点以便进一步分析。 【关键词】Winpcap;数据包;捕获;分析

The Capture and Analysis of Network Data Packets Wang Hang (Grade 11,Class 1, Major Network Engineering, Scho ol of Mathematics and Computer Science Dept, Shaanxi University of Technology, Hanzhong 723003, Shaanxi) Tutor: Jia Wei Abstract: The capture of network data packets plays an important part in network security, which is helpful for our better analysis of network data flow.This paper is about a network monitoring tool based on Windows system, which emphasizes particularly on realizing the capture and analysis of network data packets and then displays them. Take analysis as an example, it will check the type of the IP protocol, the source address of IP, the destination address of IP and the port https://www.doczj.com/doc/0b15033440.html,e the Winpcap(Windows Packet Capture)to capture of data packets. In MFC programming of VC++6.0, the capture of network data packets can be realized via the invoking and control of the functions through a full control panel, and then the analysis of IP ,TCP,UDP and TCP/IP will be done before they are displayed. Certainly the information captured can be saved to the appointed destination in order to go through an advanced analysis. Key words:Winpcap;Data Packets;Capture;Analysis

内核协议栈数据包转发完全解析

内核协议栈数据包转发 目录 1 NAPI流程与非NAPI 1.1NAPI驱动流程 1.2非NAPI流程 1.3NAPI和非NAPI的区别 2内核接受数据 2.1数据接收过程 2.2 采取DMA技术实现 3 e100采用NAPI接收数据过程 3.1 e100_open 启动e100网卡 3.2 e100_rx_alloc_list 建立环形缓冲区 3.3 e100_rx_alloc_skb 分配skb缓存 3.4 e100_poll 轮询函数 3.5 e100_rx_clean 数据包的接收和传输 3.6 e100_rx_indicate 4 队列层 4.1、软中断与下半部 4.2、队列层 5采用非NAPI接收数据过程 5.1netif_rx 5.2轮询与中断调用netif_rx_schedule不同点 5.3 netif_rx_schedule 5.4 net_rx_action 5.5 process_backlog 6数据包进入网络层 6.1 netif_receive_skb(): 6.2 ip_rcv(): 6.3 ip_rcv_finish(): 6.4 dst_input(): 6.5本地流程ip_local_deliver: 6.6转发流程ip_forward(): 1 NAPI流程与非NAPI 1.1NAPI驱动流程: 中断发生 -->确定中断原因是数据接收完毕(中断原因也可能是发送完毕,DMA完毕,甚至是中断通道上的其他设备中断) -->通过netif_rx_schedule将驱动自己的napi结构加入softnet_data的poll_list 链表,禁用网卡中断,并发出软中断NET_RX_SOFTIRQ -->中断返回时触发软中断调用相应的函数net_rx_action,从softnet_data的poll_list

数据包捕获与解析

数据包捕获与解析课程设计报告 学生姓名:董耀杰 学号:1030430330 指导教师:江珊珊

数据包捕获与分析 摘要本课程设计通过Ethereal捕捉实时网络数据包,并根据网络协议分析流程对数据包在TCP/IP各层协议中进行实际解包分析,让网络研究人员对数据包的认识上升到一个感性的层面,为网络协议分析提供技术手段。最后根据Ethereal的工作原理,用Visual C++编写一个简单的数据包捕获与分析软件。 关键词协议分析;Ethereal;数据包;Visual C++ 1引言 本课程设计通过技术手段捕获数据包并加以分析,追踪数据包在TCP/IP各层的封装过程,对于网络协议的研究具有重要的意义。Ethereal是当前较为流行的图形用户接口的抓包软件,是一个可以用来监视所有在网络上被传送的包,并分析其内容的程序。它通常被用来检查网络工作情况,或是用来发现网络程序的bugs。通过ethereal对TCP、UDP、SMTP、telnet和FTP等常用协议进行分析,非常有助于网络故障修复、分析以及软件和协议开发。,它以开源、免费、操作界面友好等优点广为世界各地网络研究人员使用为网络协议分析搭建了一个良好的研究平台。 1.1课程设计的内容 (1)掌握数据包捕获和数据包分析的相关知识; (2)掌握Ethreal软件的安装、启动,并熟悉用它进行局域网数据捕获和分析的功能; (3)设计一个简单的数据包捕获与分析软件。 1.2课程设计的要求 (1)按要求编写课程设计报告书,能正确阐述设计结果。 (2)通过课程设计培养学生严谨的科学态度,认真的工作作风和团队协作精神。 (3)学会文献检索的基本方法和综合运用文献的能力。 (4)在老师的指导下,要求每个学生独立完成课程设计的全部内容。

Linux内核发送构造数据包的方式

本文欢迎自由转载,但请标明出处,并保证本文的完整性。 作者:Godbach 日期:2009/09/01 Normal 7.8 磅 2 false false false MicrosoftInternetExplorer4 st1\:*{behavior:url(#ieooui) } /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan;

font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} 一、构造数据包简析 这里并不详细介绍如何在内核中构造数据包,下文如有需要会在适当的位置进行分析。这里简单的分析讲一下内核态基于Netfilter框架构造数据包的方式。 内核中可以用到的构造数据包的方式,个人认为可以分为两种。 其一,我们直接用alloc_skb申请一个skb结构体,然后根据实际的应用填充不同的成员,或者基于当前数据包的skb,调用skb_copy_expand()函数等新申请一个nskb,并且拷贝skb的内容。 其二,也是个人比较常用的,就是直接在先前接收到的数据包skb上作修改,主要有源IP、目IP,如果是TCP/UDP协议的话,还有源端口目的端口号。总之,就是根据自己的需求去调整数据包的相关成员即可。 通常,这两种方式最终可能都要涉及到重新计算各个部分的校验和,这也是必须的。 二、如何发送构造的数据包 承接上文,数据包已经构造完毕,下一步关键就是如何发送数据包了。个人这里总结的有两种方法。 方法一,就是让数据包接着按照Netfilter的流程进行传输。因为数据包的一些内容已经被更改,尤其是当源IP和目的IP被更改,主要是交换的情况下,是需要确保有路由可查的。 NF框架中查路由的位置一是在PREROUTING之后,而是在LOCALOUT之后。又由于这里是需要将数据包从本地发送出去。因此,可以考虑让修改后的数据包从LOCALOUT 点发出。 内核代码中有这种方式的典型体现。本文涉及的相关内核代码的版本都是2.6.18.3。源文件为ipt_REJECT.c,函数send_reset用于往当前接收到数据包的源IP上发送RST 包,整个函数涉及了数据包的构造和发送,这里一起做个简单分析。 /* Send RST reply */ static void send_reset(struct sk_buff *oldskb, int hook) { struct sk_buff *nskb; struct iphdr *iph = oldskb->nh.iph; struct tcphdr _otcph, *oth, *tcph; struct rtable *rt; u_int16_t tmp_port; u_int32_t tmp_addr; int needs_ack; int hh_len; /* 判断是否是分片包*/

Ip数据包捕获设计报告

解析IP数据包程序设计与实现 学生姓名:梁帅指导老师:谢晓巍 摘要现如今,计算机网络已经彻彻底底地改变了人们的生活。大量的数据都是经过计算机网络传输的,而TCP/IP协议是计算机网络中最重要的协议之一。计算机网络中绝大多数数据都是以IP数据包的形式发送和接受的。所以IP数据包的捕获是很多计算机安全技术的基础。本课程设计实现了可以捕获流经本地网卡的IP数据包并将其头部信息解析输出的程序。 关键词TCP/IP;IP数据包;计算机网络;捕获

Design and implementation of IP data packet Student name: LIANG Shuai Advisor:XIE Xiao-wei Abstract Nowadays, computer network has completely changed people's life. A large amount of data is transmitted through computer networks, and the TCP/IP protocol is one of the most important protocols in computer networks. Most of the data in the computer network are sent and received in the form of IP data packets. So IP packet capture is the basis of many computer security technology. This course is designed to capture the IP data packet that flows through the local network card and the program to parse the output of its head. Key words TCP/IP;IP data packet;Computer network;Capture

实验1:网络数据包的捕获与协议分析

实验报告 ( 2014 / 2015 学年第二学期) 题目:网络数据包的捕获与协议分析 专业 学生姓名 班级学号 指导教师胡素君 指导单位计算机系统与网络教学中心 日期2015.5.10

实验一:网络数据包的捕获与协议分析 一、实验目的 1、掌握网络协议分析工具Wireshark的使用方法,并用它来分析一些协议; 2、截获数据包并对它们观察和分析,了解协议的运行机制。 二、实验原理和内容 1、tcp/ip协议族中网络层传输层应用层相关重要协议原理 2、网络协议分析工具Wireshark的工作原理和基本使用规则 三、实验环境以及设备 Pc机、双绞线、局域网 四、实验步骤 1.用Wireshark观察ARP协议以及ping命令的工作过程: (1)打开windows命令行,键入“ipconfig -all”命令获得本机的MAC地址和缺省路由器的IP地址;结果如下: (2)用“arp -d”命令清空本机的缓存;结果如下 (3)开始捕获所有属于ARP协议或ICMP协议的,并且源或目的MAC地址是本机的包。(4)执行命令:ping https://www.doczj.com/doc/0b15033440.html,,观察执行后的结果并记录。

此时,Wireshark所观察到的现象是:(截图表示) 2.设计一个用Wireshark捕获HTTP实现的完整过程,并对捕获的结果进行分析和统计。(截 图加分析) 3.设计一个用Wireshark捕获ICMP实现的完整过程,并对捕获的结果进行分析和统计。要求:给出捕获某一数据包后的屏幕截图。以16进制形式显示其包的内容,并分析该ICMP 报文。(截图加分析) 4. 设计一个用Wireshark捕获IP数据包的过程,并对捕获的结果进行分析和统计(截图加分析) 要求:给出捕获某一数据包后的屏幕截图。以16进制形式显示其包的内容,并分析在该数据包中的内容:版本首部长度、服务类型、总长度、标识、片偏移、寿命、协议、源Ip地址、目的地址 五、实验总结

IP及IPSEC协议数据包的捕获与分析分析

IP及IPSEC协议数据包的捕获与分析 为了掌握掌握IP和IPSEC协议的工作原理及数据传输格式,熟悉网络层的协议。我进行了以下实验:首先用两台PC互ping并查看其IP报文,之后在两台PC上设置IPSEC互ping并查看其报文。最终分析两者的报文了解协议及工作原理。 一、用两台PC组建对等网: 将PC1与PC2连接并分别配置10.176.5.119和10.176.5.120的地址。如图1-1所示。 图1-1 二、两PC互ping: IP数据报结构如图1-2所示。 图1-2 我所抓获的报文如图1-3,图1-4所示:

图1-3 请求包 图1-4 回应包 分析抓获的IP报文: (1)版本:IPV4 (2)首部长度:20字节 (3)服务:当前无不同服务代码,传输忽略CE位,当前网络不拥塞

(4)报文总长度:60字节 (5)标识该字段标记当前分片为第1367分片 (6)三段标志分别指明该报文无保留、可以分段,当前报文为最后一段 (7)片偏移:指当前分片在原数据报(分片前的数据报)中相对于用户数据字段 的偏移量,即在原数据报中的相对位置。 (8)生存时间:表明当前报文还能生存64 (9)上层协议:1代表ICMP (10)首部校验和:用于检验IP报文头部在传播的过程中是否出错 (11)报文发送方IP:10.176.5.120 (12)报文接收方IP:10.176.5.119 (13)之后为所携带的ICMP协议的信息:类型0指本报文为回复应答,数据部分 则指出该报文携带了32字节的数据信息,通过抓获可看到内容为:abcdefghijklmnopqrstuvwabcdefghi 三、IPSec协议配置: 1、新建一个本地安全策略。如图1-5。 图1-5 2、添加IP安全规则。如图1-6.

网络数据包分析实验

实验一:网络数据包分析实验 班级:班学号:姓名:一、实验目的 通过对实际的网络数据包进行捕捉,分析数据包的结构,加深对网络协议分层概念的理解,并实际的了解数据链路层,网络层,传输层以及应用层的相关协议和服务。 、实验内容 1. IGMP包解析 1.1数据链路层 El代XEL洱丁;亡日:亡5 MB)」osr: IP- 4m 4 t-is :hi-At I _n * tP f Ld L^iJ 1 Sei 00:00:1^^ saur-ctt El1imro_&ai?SiU Type;IP CgMOsw) 源数据: 数据链路层头部:01 00 5e 00 00 16 00 21 97 0a e5 16 08 00 数据链路层尾部:00 00 00 00 00 00 分析如下:

数据头部的前6个字节是接收者的mac地址:01 00 5e 00 00 16 数据头部的中间6个字节是发送者的mac地址:00 21 97 0a e5 16 数据头部的最后2个字节代表网络协议,即:08 00协议类型。 1.2网络层 Header* 1 cngth: 24 byres n axed services "乜Id:0x00 (.DSCP 0X00: D&fau11: 0x003 Tqtil rength:斗D Tdsrrtificar I cn: QklclJ 也^7460) H Flmqs: Q>00 Fra^Tienr offset;:Q Time VQ live; 1 Fr DTCCDl : IGMP go?) ¥ HPAder fhecksijn:CxJ85c [correct] 5DU RUM;172,10.103.?0

网络数据包收发流程1

网络数据包收发流程(1):从驱动到协议栈 2013-06-26 14:47:19 标签:控制器数据包以太网网络流量 原文出处:https://www.doczj.com/doc/0b15033440.html,/uid-24148050-id-464587.html 一、硬件环境 intel82546:PHY与MAC集成在一起的PCI网卡芯片,很强大 bcm5461:PHY芯片,与之对应的MAC是TSEC TSEC:Three Speed Ethernet Controller,三速以太网控制器,PowerPc 架构CPU里面的MAC 模块 注意,TSEC内部有DMA子模块 话说现在的CPU越来越牛叉了,什么功能都往里面加,最常见的如MAC功能。 TSEC只是MAC功能模块的一种,其他架构的cpu也有和TSEC类似的MAC功能模块。 这些集成到CPU芯片上的功能模块有个学名,叫平台设备,即platform device。 二、网络收包原理 网络驱动收包大致有3种情况: no NAPI:mac每收到一个以太网包,都会产生一个接收中断给cpu,即完全靠中断方式来收包 缺点是当网络流量很大时,cpu大部分时间都耗在了处理mac的中断。 netpoll:在网络和I/O子系统尚不能完整可用时,模拟了来自指定设备的中断,即轮询收包。缺点是实时性差 NAPI:采用中断+ 轮询的方式:mac收到一个包来后会产生接收中断,但是马上关闭。直到收够了netdev_max_backlog个包(默认300),或者收完mac上所有包后,才再打开接收中断 通过sysctl来修改https://www.doczj.com/doc/0b15033440.html,dev_max_backlog 或者通过proc修改/proc/sys/net/core/netdev_max_backlog

IP及IPSEC协议数据包的捕获与分析

IP及IPSEC协议数据包的捕获与分析

IP及IPSEC协议数据包的捕获与分析 为了掌握掌握IP和IPSEC协议的工作原理及数据传输格式,熟悉网络层的协议。我进行了以下实验:首先用两台PC互ping并查看其IP报文,之后在两台PC上设置IPSEC互ping并查看其报文。最终分析两者的报文了解协议及工作原理。 一、用两台PC组建对等网: 将PC1与PC2连接并分别配置10.176.5.119和10.176.5.120的地址。如图1-1所示。 图1-1 二、两PC互ping: IP数据报结构如图1-2所示。 图1-2 我所抓获的报文如图1-3,图1-4所示:

图1-3 请求包 图1-4 回应包 分析抓获的IP报文: (1)版本:IPV4 (2)首部长度:20字节 (3)服务:当前无不同服务代码,传输忽略CE位,当前网络不拥塞

(4)报文总长度:60字节 (5)标识该字段标记当前分片为第1367分片 (6)三段标志分别指明该报文无保留、可以分段,当前报文为最后一段 (7)片偏移:指当前分片在原数据报(分片前的数据报)中相对于用户数据字段 的偏移量,即在原数据报中的相对位置。 (8)生存时间:表明当前报文还能生存64 (9)上层协议:1代表ICMP (10)首部校验和:用于检验IP报文头部在传播的过程中是否出错 (11)报文发送方IP:10.176.5.120 (12)报文接收方IP:10.176.5.119 (13)之后为所携带的ICMP协议的信息:类型0指本报文为回复应答,数据部分 则指出该报文携带了32字节的数据信息,通过抓获可看到内容为:abcdefghijklmnopqrstuvwabcdefghi 三、IPSec协议配置: 1、新建一个本地安全策略。如图1-5。 图1-5 2、添加IP安全规则。如图1-6.

FTP数据包的详细分析

FTP协议分析与源码阅读 一、什么是FTP协议 Transfer Protocal),是文件传输协议的简称。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序(Application)。用户可以通过它把自己的PC机与世界各地所有运行FTP协议的服务器相连,访问服务器上的大量程序和信息。 Transfer Protocol) 1、FTP的作用: 正如其名所示:FTP的主要作用,就是让用户连接上一个远程计算机(这些计算机上运行着FTP服务器程序)察看远程计算机有哪些文件,然后把文件从远程计算机上拷到本地计算机,或把本地计算机的文件送到远程计算机去。 2、FTP工作原理 拿下传文件为例,当你启动FTP从远程计算机拷贝文件时,你事实上启动了两个程序:一个本地机上的FTP客户程序:它向FTP服务器提出拷贝文件的请求。另一个是启动在远程计算机的上的FTP服务器程序,它响应你的请求把你指定的文件传送到你的计算机中。FTP采用“客户机/服务器”方式,用户端要在自己的本地计算机上安装FTP客户程序。FTP 客户程序有字符界面和图形界面两种。字符界面的FTP的命令复杂、繁多。图形界面的FTP 客户程序,操作上要简洁方便的多。简单地说,支持FTP协议的服务器就是FTP服务器,下面介绍一下什么是FTP协议(文件传输协议) 一般来说,用户联网的首要目的就是实现信息共享,文件传输是信息共享非常重要的一个内容之一。Internet上早期实现传输文件,并不是一件容易的事,我们知道Internet是一个非常复杂的计算机环境,有PC,有工作站,有MAC,有大型机,据统计连接在Internet 上的计算机已有上千万台,而这些计算机可能运行不同的操作系统,有运行Unix的服务器,也有运行Dos、Windows的PC机和运行MacOS的苹果机等等,而各种操作系统之间的文件交流问题,需要建立一个统一的文件传输协议,这就是所谓的FTP。基于不同的操作系统有不同的FTP应用程序,而所有这些应用程序都遵守同一种协议,这样用户就可以把自己的文件传送给别人,或者从其它的用户环境中获得文件。 与大多数Internet服务一样,FTP也是一个客户机/服务器系统。用户通过一个支持FTP 协议的客户机程序,连接到在远程主机上的FTP服务器程序。用户通过客户机程序向服务器程序发出命令,服务器程序执行用户所发出的命令,并将执行的结果返回到客户机。比如说,用户发出一条命令,要求服务器向用户传送某一个文件的一份拷贝,服务器会响应这条命令,将指定文件送至用户的机器上。客户机程序代表用户接收到这个文件,将其存放在用户目录中。 在FTP的使用当中,用户经常遇到两个概念:"下载"(Download)和"上载"(Upload)。"下载"文件就是从远程主机拷贝文件至自己的计算机上;"上载"文件就是将文件从自己的计算机中拷贝至远程主机上。用Internet语言来说,用户可通过客户机程序向(从)远程主机上载(下载)文件。 使用FTP时必须首先登录,在远程主机上获得相应的权限以后,方可上载或下载文件。也就是说,要想同哪一台计算机传送文件,就必须具有哪一台计算机的适当授权。换言之,除非有用户ID和口令,否则便无法传送文件。这种情况违背了Internet的开放性,Internet 上的FTP主机何止千万,不可能要求每个用户在每一台主机上都拥有帐号。匿名FTP就是为解决这个问题而产生的。 匿名FTP是这样一种机制,用户可通过它连接到远程主机上,并从其下载文件,而无

网络数据包协议分析

网络数据包协议分析 一、实验目的 1.学习网络协议分析工具Ethereal的使用方法; 2.截获数据并对它们观察,分析其中2中协议(arp&tcp)数据包包头各数据位的含义, 了解协议的运行机制。 二、实验步骤 1.安装并打开Ethereal软件; 2.利用”运行cmd”打开命令提示符,输入“ping”确认网络连接是否完成; 3.点击capture->options选择网卡(默认有线); 4.点击capture开始抓包; 5.打开浏览器,访问一个网站,这样才可以抓到tcp的数据包; 6.点击stop停止抓包。 三、实验结果分析 1.Arp---address resolution protocol,地址解析协议的缩写,就是主机在发送帧前将目 标IP地址(32位)转换成目标MAC地址(48位)的过程。它属于链路层的协议。

ARP协议数据包包头数据位分析: 1.第一栏显示帧信息。 Frame 280 (60 bytes on wire,60 bytes capture)是指该数据包含有60个字节,ethereal软件截获了60个字节。点击打开,里面包括了到达时间、相对前一个包的时间延迟、传输时间、帧号280、包长度(60字节)和捕获到的长度(60字节)。 2.第二栏显示以太网信息。 源MAC地址是f4:6d:04:3a:62:33,目的MAC地址是ff:ff:ff:ff:ff:ff。 3.第三栏显示因特网协议信息。 它包括了硬件类型:以太网;协议类型是IP协议和发送方的IP地址与MAC地址,也包括了目的IP地址和MAC地址。 2.tcp—transition control protocol,传输控制协议的缩写。是一种面向连接(连接导向) 的、可靠的、基于字节流的传输层通信协议。

Linux内核分-(详细)收发数据包的调用

Linux内核分析- 网络[一]:收发数据包的调用 分类:内核协议栈2010-12-01 15:08 7355人阅读评论(7) 收藏举报 linux内核网络structlistaction 内核版本:Linux-2.6.34 网卡驱动:B4401 什么是NAPI NAPI是linux一套最新的处理网口数据的API,linux 2.5引入的,所以很多驱动并不支持这种操作方式。简单来说,NAPI是综合中断方式与轮询方式的技术。数据量很低与很高时,NAPI 可以发挥中断方式与轮询方式的优点,性能较好。如果数据量不稳定,且说高不高说低不低,则NAPI会在两种方式切换上消耗不少时间,效率反而较低一些。 下面会用到netdev_priv()这个函数,这里先讲解下,每个网卡驱动都有自己的私有的数据,来维持网络的正常运行,而这部分私有数据放在网络设备数据后面(内存概念上),这个函数就是通过dev来取得这部分私有数据,注间这部分私有数据不在dev结构体中,而是紧接在dev内存空间后。 static inline void *netdev_priv(const struct net_device *dev) { return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN); } 弄清这个函数还得先清楚dev这个结构的分配 alloc_netdev() -> alloc_netdev_mq() struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, void (*setup)(struct net_device *), unsigned int queue_count) { …… alloc_size = sizeof(struct net_device); if (sizeof_priv) { /* ensure 32-byte alignment of private area */ alloc_size = ALIGN(alloc_size, NETDEV_ALIGN); alloc_size += sizeof_priv; } /* ensure 32-byte alignment of whole construct */ alloc_size += NETDEV_ALIGN - 1; p = kzalloc(alloc_size, GFP_KERNEL); if (!p) { printk(KERN_ERR "alloc_netdev: Unable to allocate device./n");

数据包抓包分析

数据链路层数据包抓包分析 实验内容 (1)安装Wireshark软件。 (2)掌握抓包软件的使用 (3)掌握通过抓包软件抓取帧并进行分析的办法 实验步骤 (1)常用的抓包软件包括Sniffer、NetXRay、Wireshark (又名EtheReal)。 我们采用免费的Wireshark,可以从https://www.doczj.com/doc/0b15033440.html,或其他网站下载。安装完成后,Wireshark的主界面和各模块功能如下: 命令菜单(command menus):最常用菜单命令有两个:File、Capture。File菜单允许你保存捕获的分组数据或打开一个已被保存的捕获分组数据文件。Capture菜单允许你开始捕获分组。 显示筛选规则(display filter specification):在该字段中,可以填写协议的名称或其他信息,根据此内容可以对分组列表窗口中的分组进行过滤。 捕获分组列表(listing of captured packets):按行显示已被捕获的分组内容,其中包括:Wireshark赋予的分组序号、捕获时间、分组的源地址和目的地址、协议类型、分组中所包含的协议说明信息。在该列表中,所显示的协议类型是发送或接收分组的最高层协议的类型。分组首部明细(details of selected packet header):显示捕获分组列表窗口中被选中分组的头部详细信息。包括:与以太网帧有关的信息,与包含在该分组中的IP数据报有关的信息。如果利用TCP或UDP承载分组, Wireshark也会显示TCP或UDP协议头部信息。最后,分组最高层协议的头部字段也会被显示。 分组内容窗口(packet content):以ASCII码和十六进制两种格式显示被捕获帧的完整内容。(2)下面我们进行抓包练习。 在capture菜单中选中options,可以设置抓包选项,如下图所示,这里我们需要选

计算机网络实验八 Sniffer Pro数据包捕获与协议分析汇编

惠州学院《计算机网络》实验报告 实验08 Sniffer Pro数据包捕获与协议分析 1. 实验目的 (1)了解Sniffer的工作原理。 (2)掌握SnifferPro工具软件的基本使用方法。 (3)掌握在非交换以太网环境下侦测、记录、分析数据包的方法。 2. 实验原理 数据在网络上是以很小的被称为“帧”或“包”的协议数据单元(PDU)方式传输的。以数据链路层的“帧”为例,“帧”由多个部分组成,不同的部分对应不同的信息以实现相应的功能,例如,以太网帧的前12个字节存放的是源MAC地址和目的MAC地址,这些数据告诉网络该帧的来源和去处,其余部分存放实际用户数据、高层协议的报头如TCP/IP 的报头或IPX报头等等。帧的类型与格式根据通信双方的数据链路层所使用的协议来确定,由网络驱动程序按照一定规则生成,然后通过网络接口卡发送到网络中,通过网络传送到它们的目的主机。目的主机按照同样的通信协议执行相应的接收过程。接收端机器的网络接口卡一旦捕获到这些帧,会告诉操作系统有新的帧到达,然后对其进行校验及存储等处理。 在正常情况下,网络接口卡读入一帧并进行检查,如果帧中携带的目的MAC地址和自己的物理地址一致或者是广播地址,网络接口卡通过产生一个硬件中断引起操作系统注意,然后将帧中所包含的数据传送给系统进一步处理,否则就将这个帧丢弃。 如果网络中某个网络接口卡被设置成“混杂”状态,网络中的数据帧无论是广播数据帧还是发向某一指定地址的数据帧,该网络接口卡将接收所有在网络中传输的帧,这就形成了监听。如果某一台主机被设置成这种监听(Snfffing)模式,它就成了一个Sniffer。 一般来说,以太网和无线网被监听的可能性比较高,因为它们是一个广播型的网络,当然无线网弥散在空中的无线电信号能更轻易地截获。 3. 实验环境与器材 本实验在虚拟机中安装SnifferPro4.7版本,要求虚拟机开启FTP、HTTP等服务,即虚拟机充当服务器,物理机充当工作站。 物理机通过Ping命令、FTP访问及网页访问等操作实验网络数据帧的传递。 4. 实验内容 介绍最基本的网络数据帧的捕获和解码,详细功能请参阅本教材辅助材料。 (1)Sniffer Pro 4.7的安装与启动 1)启动Sniffer Pro 4.7。在获取Sniffer Pro 4.7软件的安装包后,运行安装程序,按要求输入相关信息并输入注册码,若有汉化包请在重启计算机前进行汉化。完成后重启计算机,点击“开始”→“程序”→“Sniffer Pro”→“Sniffer”,启动“Sniffer Pro 4.7”程序。 2)选择用于Sniffer的网络接口。如果计算机有多个网络接口设备,则可通过菜单“File”→“Select Settings”,选择其中的一个来进行监测。若只有一块网卡,则不必进行此步骤。

IP 数据报捕获与分析实验报告

实验报告 专业班级成绩评定______ 学号姓名教师签名______ 实验题目IP 数据报捕获与分析实验时间 一、实验目的: 1.掌握IP数据报格式。 2.理解IP协议的工作原理及工作过程。 3.掌握使用wireshark捕获IP等数据报并分析。 二、实验环境:以太网。 三、实验内容: 1.熟悉WinPcap的体系构架和提供的函数。 2.学习IP数据报校验和计算方法。 3.掌握使用wireshark捕获IP等数据报。 4.对捕获的IP数据报进行分析。 四、实验步骤: 1.在PING之前先运行wireshark熟悉页面并进行一些设置

a.单击Capture Filter过滤器:可以设置捕捉一些特殊规则 的数据报。 b.在选中Capture packets in promiscuous mode:可以设置 为混合全处理模式。 c.可以点击Start开始捕捉。过一段时间后,点击Stop停止, 观察捕捉到的数据报,并进行分析。 2.使用wireshark捕获和分析IP数据包。 a.打开wireshar并开始捕获数据包。 b.然后在系统的“开始”—“运行”—输入“CMD”命令,进 入DOS命令窗口,并输入“ping”命令测试网络的情况. c.如“ping 192.168.0.1”。 Ping 命令的使用

d.再回到wireshar点击停止后查看捕获到的数据,双击打开 “ping”后的数据包,分析数据包的内容。 分片的数据包 (以下图片全部通过wireshark捕获数据包,然后用QQ中的截图功能截取) IP协议节点

IP协议节点 上面节点说明如下: 3.进制数据包窗口 16进制数据包窗口将数据包的所有内容以16进制的形式显示出来,如下所示:

解析IP数据包课程设计

课程设计任务书 目录 1.实验目的 2.实验要求 ) 3.预备知识 4.课程设计分析 5.实现过程 6.程序流程图 ! 7.相关扩展 8.实习体会

9.参考文献 一.实验目的: 设计一个解析IP数据包的程序,并根据这个程序,说明IP数据包的结构及IP协议的相 关问题,从而IP层的工作原理有更好的理解和认识. 、 二.实验要求: 本设计的目标是捕获网络中数据包,解析数据包的内容,将、结果显示在标准输出上, 并同时写入日志文件. 程序的具体要求如下: 3)以命令行形式运行:ipparse logfile,其中ipparse是程序名,而logfile则代表记录 结果的日志文件. 4)在标准输出和日志文件中写入捕获的IP数据包的版本,头长度,服务类型,数据包总长 度,数据包标识,分段标志,分段偏移值,生存时间,上层协议类型,头校验和,源IP地址 和目的IP地址等内容. 当程序接收到键盘输入Ctrl+C时退出. ~ 三.预备知识 互联网络层是TCP/IP协议参考模型中的关键部分.IP协议把传输层送来的消息组装成IP数据包,并把IP数据包传送给数据链层.IP协议在TCP/IP协议族中处于核心地 位,IP协议制定了统一的IP数据包格式,以消除个通信子网中的差异,从而为信息发送 方和接收方提供了透明的传输通道.编制本程序前,首先要对IP包的格式有一定了解, 图1给出了IP协议的数据包格式. IP数据包的第一个字段是版本字段,其度是4位,表示所使用的IP协议的版本.目前的版本是IPV4,版本字段的值是4,下一代版本是IPV6,版本字段值是6.本程序主要 针对版本是IPV4的数据包的解析. 报头标长字段为4位,它定义了以4B为一个单位的IP包的报文长度.报头中除了选项字段和填充域字段外,其他各字段是定长的.因此,IP数据包的头长度在20—40B 之间,是可变的. 0 4 8 16 19 24 31

相关主题
文本预览
相关文档 最新文档