这一篇主要围绕网络协议接口层的发送函数的解析



#### int dev_queue_xmit(struct sk_buff *skb) 函数解析

  • 声明:
    /*  include/linux/netdevice.h  */
int dev_queue_xmit(struct sk_buff *skb);
  • 定义:
    /*  net/core/dev.c   */
int dev_queue_xmit(struct sk_buff *skb)
{
return __dev_queue_xmit(skb, NULL);
}
EXPORT_SYMBOL(dev_queue_xmit); /* __dev_queue_xmit() */
/**
* __dev_queue_xmit - transmit a buffer 传输一个缓冲区
* @skb: buffer to transmit 需要传输的缓冲区
* @accel_priv: private data used for L2 forwarding offload 需要顺带一起送过去的个人数据
* 将缓冲区制作成队列传输到一个网络设备,这个函数的使用必须先设置设备和优先级,
* 而且要先创建一个缓冲区在调用它之前,这个函数可以在一个中断中被调用。
* Queue a buffer for transmission to a network device. The caller must
* have set the device and priority and built the buffer before calling
* this function. The function can be called from an interrupt.
* 一个否定的错误码是返回一个错误数字,成功并不保证帧即将传输,
* 他可以因为缓冲向下传输造成堵塞或者流量控制。
* A negative errno code is returned on a failure. A success does not
* guarantee the frame will be transmitted as it may be dropped due
* to congestion or traffic shaping.
*
* -----------------------------------------------------------------------------------
* I notice this method can also return errors from the queue disciplines,
* including NET_XMIT_DROP, which is a positive value. So, errors can also
* be positive.
*
* Regardless of the return value, the skb is consumed, so it is currently
* difficult to retry a send to this method. (You can bump the ref count
* before sending to hold a reference for retry if you are careful.)
*
* When calling this method, interrupts MUST be enabled. This is because
* the BH enable code must have IRQs enabled so that it will not deadlock.
* --BLG
*/ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
{
struct net_device *dev = skb->dev; // 网络设备结构体
struct netdev_queue *txq; // 网络设备队列结构体
struct Qdisc *q; // 排队准则结构体
int rc = -ENOMEM; skb_reset_mac_header(skb); // 这里是计算了套接字头到数据的这段大小 // 这里告诉cpu 这种概率不是很大,但是有可能是真的,我比较倾向是假的
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_SCHED_TSTAMP))
__skb_tstamp_tx(skb, NULL, skb->sk, SCM_TSTAMP_SCHED); /* Disable soft irqs for various locks below. Also
* stops preemption for RCU.
*/
rcu_read_lock_bh(); skb_update_prio(skb); /* If device/qdisc don't need skb->dst, release it right now while
* its hot in this cpu cache.
*/
/* 检查netdevice的flag 是否要去掉skb DTS相关的信息,一般情况下这个flag是默认被设置的。
* 在alloc_netdev_mqs 的时候,已经被默认设置了。
*/
if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
skb_dst_drop(skb);
else
skb_dst_force(skb); #ifdef CONFIG_NET_SWITCHDEV
/* Don't forward if offload device already forwarded */
if (skb->offload_fwd_mark &&
skb->offload_fwd_mark == dev->offload_fwd_mark) {
consume_skb(skb);
rc = NET_XMIT_SUCCESS;
goto out;
}
#endif
/* 这里是要取出此netdevice的txq和txq的Qdisc, Qdisc主要是用于进行堵塞处理
* 一般情况下,直接将数据包给driver了,如果遇到busy的情况,就需要进行阻塞处理了,就会用到Qdisc
*/
txq = netdev_pick_tx(dev, skb, accel_priv);
q = rcu_dereference_bh(txq->qdisc); #ifdef CONFIG_NET_CLS_ACT
skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
#endif
trace_net_dev_queue(skb);
/* 检查Qdisc 中是否存在enqueue规则,如果有就会调用__dev_xmit_skb,进入带有阻塞的控制的Flow,
* 注意这个地方,虽然是走阻塞控制的,Flow但是并不一定进行enqueue操作,只有busy的情况下,
* 才会走Qdisc的enqueue 操作进行
*/
if (q->enqueue) {
rc = __dev_xmit_skb(skb, q, dev, txq);
goto out;
} /* The device has no queue. Common case for software devices:
loopback, all the sorts of tunnels... Really, it is unlikely that netif_tx_lock protection is necessary
here. (f.e. loopback and IP tunnels are clean ignoring statistics
counters.)
However, it is possible, that they rely on protection
made by us here. Check this and shot the lock. It is not prone from deadlocks.
Either shot noqueue qdisc, it is even simpler 8)
*/
/* 如果Qdisc 的enqueue 不存在,就会到这里,
* 对于一些loopback/tunnel interface 比较常见,判断设备是不是UP状态
*/
if (dev->flags & IFF_UP) {
int cpu = smp_processor_id(); /* ok because BHs are off */ if (txq->xmit_lock_owner != cpu) { if (__this_cpu_read(xmit_recursion) > RECURSION_LIMIT)
goto recursion_alert; skb = validate_xmit_skb(skb, dev);
if (!skb)
goto drop; HARD_TX_LOCK(dev, txq, cpu);
/* 如果txq 不是stop 状态,那么就会调用dev_hard_start_xmit 函数发送数据 */
if (!netif_xmit_stopped(txq)) {
__this_cpu_inc(xmit_recursion);
skb = dev_hard_start_xmit(skb, dev, txq, &rc);
__this_cpu_dec(xmit_recursion);
if (dev_xmit_complete(rc)) {
HARD_TX_UNLOCK(dev, txq);
goto out;
}
}
HARD_TX_UNLOCK(dev, txq);
net_crit_ratelimited("Virtual device %s asks to queue packet!\n",
dev->name);
} else {
/* Recursion is detected! It is possible,
* unfortunately
*/
recursion_alert:
net_crit_ratelimited("Dead loop on virtual device %s, fix it urgently!\n",
dev->name);
}
} rc = -ENETDOWN;
drop:
rcu_read_unlock_bh(); atomic_long_inc(&dev->tx_dropped);
kfree_skb_list(skb);
return rc;
out:
rcu_read_unlock_bh();
return rc;
}

Linux 网络子系统之网络协议接口层(二)的更多相关文章

  1. Linux 网络子系统之网络协议接口层(一)

    Linux 网络设备驱动之网络协议接口层介绍. 网络协议接口层最主要的功能是给上层协议提供透明的数据包发送和接收接口. 当上层ARP或IP需要发送数据包时,它将调用网络协议接口层的dev_queue_ ...

  2. Linux中断(interrupt)子系统之四:驱动程序接口层 & 中断通用逻辑层【转】

    转自:http://blog.csdn.net/droidphone/article/details/7497787 在本系列文章的第一篇:Linux中断(interrupt)子系统之一:中断系统基本 ...

  3. Linux时间子系统(三) 用户空间接口函数

    一.前言 从应用程序的角度看,内核需要提供的和时间相关的服务有三种: 1.和系统时间相关的服务.例如,在向数据库写入一条记录的时候,需要记录操作时间(何年何月何日何时). 2.让进程睡眠一段时间 3. ...

  4. Linux 网络子系统之结构介绍

    Linux 网络设备驱动程序的体系结构 图片说明如下: 网络协议接口层 网络协议接口层向网络层协议提供统一的数据包收发接口,不论上层协议是ARP还是IP,都通过 dev_queue_xmit() 函数 ...

  5. Linux输入子系统详解

    input输入子系统框架  linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler).输入子系统核心层(Input ...

  6. Linux网络之设备接口层:发送数据包流程dev_queue_xmit

    转自:http://blog.csdn.net/wdscq1234/article/details/51926808 写在前面 本文主要是分析kernel-3.8的源代码,主要集中在Network的n ...

  7. Linux 网络子系统

    今天记录一下Linux网络子系统相关的东西. 因为感觉对这一块还是有一个很大的空白,这件事情太可怕了. 摘抄多份博客进行总结一下Linux网络子系统的相关东西. 一. Linux网络子系统体系结构 L ...

  8. linux网络子系统内核分析

    1.选择路由 若要将数据包发至PC2,则linux系统通过查询路由表可知168.1.1.10(目的地址)的网关地址为192.168.1.1,此时linux系统选择网卡1发送数据包. 2.邻居子系统(通 ...

  9. Linux内核分析(四)----进程管理|网络子系统|虚拟文件系统|驱动简介

    原文:Linux内核分析(四)----进程管理|网络子系统|虚拟文件系统|驱动简介 Linux内核分析(四) 两天没有更新了,上次博文我们分析了linux的内存管理子系统,本来我不想对接下来的进程管理 ...

随机推荐

  1. 近年Recsys论文

    2015年~2017年SIGIR,SIGKDD,ICML三大会议的Recsys论文: [转载请注明出处:https://www.cnblogs.com/shenxiaolin/p/8321722.ht ...

  2. HTML:调用静态页面html 的几种方法

    今天做办公用品管理系统时,发现需要用到在一个静态页面html 中调用多个静态页面html的内容.查找资料总结了以下一些方法: 一.iframe引入的方法 代码如下: <!-- 部门--> ...

  3. 房产地图google map的初步应用点滴.3)(转)

    房产地图google map的初步应用点滴.1)房产地图google map的初步应用点滴.2)房产地图google map的初步应用点滴.3) 房产地图google map的初步应用点滴.4) go ...

  4. iOS - CFNetwork 的使用

    1.CFNetwork CFNetwork 是基于 OS 层 BSDSocket 封装(纯 C),用于网络通信,早期的网络请求框架 ASIHTTPRequest 就是基于 CFNetwork 进行的封 ...

  5. IIS下浏览指定文件(如:web.config)

    具体步骤如下: 1.快捷键:Ctrl + R 2.输入:%windir%\System32\inetsrv\config\applicationHost.config 3.注销:fileExtensi ...

  6. apache主机(网站)配置,port监听,文件夹訪问权限及分布式权限

    前言 一个网站的两个核心信息为: 主机名称(server名/网站名):ServerName server名 网站位置(网站文件夹路径):DocumentRoot "实际物理路径" ...

  7. spring3.0.6+hibernate3升级spring4.1.6+hibernate4.3遇到的问题

    1.下面这三个包,在hibernate4中已经废弃了,因为都直接用session来进行很好的事务管理 import org.springframework.orm.hibernate3.Hiberna ...

  8. malloc/free 与 new/delete 比较

    相同点:都可用于申请动态内存和释放内存 不同点: (1)操作对象有所不同. malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符.对于非内部数据类的对象而言,光 ...

  9. MyBatis generator 使用方式 小结

    1.  配置到 maven 中pom.xml 中 2.  手动运行 脚本文件 3. 基于 web 项目  http://git.oschina.net/redArmy/springboot-gener ...

  10. 《Effective Java》读书笔记五(枚举和注解)

    No30 用enum代替int常量 一:综述 int枚举模式,示范: // The int enum pattern - severely deficient! public static final ...