ovs 数据包的处理过程
Openvswitch的内核模块openvswitch.ko会在网卡上注册一个函数netdev_frame_hook,每当有网络包到达网卡的时候,这个函数就会被调用。
static struct sk_buff *netdev_frame_hook(struct sk_buff *skb)
{
if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
return skb;
port_receive(skb);
return NULL;
}
调用port_receive即是调用netdev_port_receive
define port_receive(skb) netdev_port_receive(skb, NULL)
void netdev_port_receive(struct sk_buff *skb, struct ip_tunnel_info *tun_info)
{
struct vport *vport;
vport = ovs_netdev_get_vport(skb->dev);
……
skb_push(skb, ETH_HLEN);
ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
ovs_vport_receive(vport, skb, tun_info);
return;
error:
kfree_skb(skb);
}
在函数int ovs_vport_receive(struct vport *vport, struct sk_buff *skb, const struct ip_tunnel_info *tun_info)实现如下
int ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
const struct ip_tunnel_info *tun_info)
{
struct sw_flow_key key;
......
/* Extract flow from 'skb' into 'key'. */
error = ovs_flow_key_extract(tun_info, skb, &key);
if (unlikely(error)) {
kfree_skb(skb);
return error;
}
ovs_dp_process_packet(skb, &key);
return 0;
}
在这个函数里面,首先声明了变量struct sw_flow_key key;可见这个key里面是一个大杂烩,数据包里面的几乎任何部分都可以作为key来查找flow表
tunnel可以作为key
在物理层,in_port即包进入的网口的ID
在MAC层,源和目的MAC地址
在IP层,源和目的IP地址
在传输层,源和目的端口号
IPV6
所以,要在内核态匹配流表,首先需要调用ovs_flow_key_extract,从包的正文中提取key的值。
接下来就是要调用ovs_dp_process_packet了。
void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key)
{
const struct vport *p = OVS_CB(skb)->input_vport;
struct datapath *dp = p->dp;
struct sw_flow *flow;
struct sw_flow_actions *sf_acts;
struct dp_stats_percpu *stats;
u64 *stats_counter;
u32 n_mask_hit;
stats = this_cpu_ptr(dp->stats_percpu);
/* Look up flow. */
flow = ovs_flow_tbl_lookup_stats(&dp->table, key, skb_get_hash(skb),
&n_mask_hit);
if (unlikely(!flow)) {
struct dp_upcall_info upcall;
int error;
memset(&upcall, 0, sizeof(upcall));
upcall.cmd = OVS_PACKET_CMD_MISS;
upcall.portid = ovs_vport_find_upcall_portid(p, skb);
upcall.mru = OVS_CB(skb)->mru;
error = ovs_dp_upcall(dp, skb, key, &upcall);
if (unlikely(error))
kfree_skb(skb);
else
consume_skb(skb);
stats_counter = &stats->n_missed;
goto out;
}
ovs_flow_stats_update(flow, key->tp.flags, skb);
sf_acts = rcu_dereference(flow->sf_acts);
ovs_execute_actions(dp, skb, sf_acts, key);
stats_counter = &stats->n_hit;
out:
/* Update datapath statistics. */
u64_stats_update_begin(&stats->syncp);
(*stats_counter)++;
stats->n_mask_hit += n_mask_hit;
u64_stats_update_end(&stats->syncp);
}
这个函数首先在内核里面的流表中查找符合key的flow,也即ovs_flow_tbl_lookup_stats,如果找到了,很好说明用户态的流表已经放入内核,则走fast path就可了。于是直接调用ovs_execute_actions,执行这个key对应的action。
如果不能找到,则只好调用ovs_dp_upcall,让用户态去查找流表。会调用static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, const struct sw_flow_key *key, const struct dp_upcall_info *upcall_info)
它会调用err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid);通过netlink将消息发送给用户态。在用户态,有线程监听消息,一旦有消息,则触发udpif_upcall_handler。
- 从Device接收Packet交给事先注册的event handler进行处理
- 接收Packet后识别是否是unknown packet,是则交由upcall处理
- vswitchd对unknown packet找到flow rule进行处理
- 将Flow rule发送给datapath
也就是说OVS处理数据包首先会看有没有事先订阅的事件,如果有直接转交给该对应的处理函数,然后匹配流表,最后按照传统网络协议栈进行处理。
ovs 数据包的处理过程的更多相关文章
- Linux内核--网络栈实现分析(七)--数据包的传递过程(下)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7545855 更多请查看专栏,地 ...
- Linux内核--网络栈实现分析(二)--数据包的传递过程--转
转载地址http://blog.csdn.net/yming0221/article/details/7492423 作者:闫明 本文分析基于Linux Kernel 1.2.13 注:标题中的”(上 ...
- [转]Linux网络 - 数据包的发送过程
转, 原文:https://segmentfault.com/a/1190000008926093 -------------------------------------------------- ...
- Linux内核--网络栈实现分析(二)--数据包的传递过程(上)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7492423 更多请看专栏,地址 ...
- Linux网络 - 数据包的接收过程【转】
转自:https://segmentfault.com/a/1190000008836467 本文将介绍在Linux系统中,数据包是如何一步一步从网卡传到进程手中的. 如果英文没有问题,强烈建议阅读后 ...
- [转]Linux网络 - 数据包的接收过程
转, 原文: https://segmentfault.com/a/1190000008836467 ------------------------------------------------- ...
- CCNA - Part10 数据包的通信过程
这篇文章主要是对数据包在同网段和不同网段的转发流程梳理,使用 ping 命令进行实际抓包测试. 网关的概念: 对于像 PC 等终端设备来说,通过交换机可以实现同网段的通信.但如果想要给其他网段发生数据 ...
- opencontrail—VXLAN模式下数据包的传输过程
在这篇文章中,我们将看到VM生成的数据包如何能够到达另一个VM或外部资源,Neutron使用OpenContrail插件的上下文中的关键概念/组件是什么. 我们将重点介绍OpenContrail,它如 ...
- Linux网络 - 数据包的接收过程(转)
https://segmentfault.com/a/1190000008836467
随机推荐
- Kubernetes 学习16 RBAC
一.概述 1.前面讲过,kubernetes的授权也是基于插件来实现而且用户访问时某一次操作经由某一授权插件检查能通过后就不再经由其它插件检查.然后由准入控制插件再做进一步后续的准入控制检查.那么在他 ...
- 【CSS】知识笔记
一.CSS文件 1.引用css文件,放在Head里面,可以减少repaint和reflow. 浏览器渲染页面大概是这样的,当浏览器从上到下一边下载html生成DOM tree一边根据浏览器默认及现有C ...
- 博客系统的使用(typecho、WordPress等等)
一.下载,解压,安装 二.Apache配置虚拟主机,(host文件修改) 三.开启php.ini中pdo类型的扩展适配数据库 四.按照指示页面配置 五.操作控制面板和blog前台
- [分享]Passcape Software - Windows Password Recovery
[分享]Passcape Software - Windows Password Recovery https://bbs.pediy.com/thread-245965.htm [[other] ...
- kafka Auto offset commit faild reblance
今天在使用python消费kafka时遇到了一些问题, 特记录一下. 场景一. 特殊情况: 单独写程序只用来生产消费数据 开始时间: 10:42 Topic: t_facedec Partition: ...
- Bzoj 2875: [Noi2012]随机数生成器(矩阵乘法)
2875: [Noi2012]随机数生成器 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 2052 Solved: 1118 Description ...
- python3 之metaclass
如果希望创建某一批类全部具有某种特征,则可通过 metaclass 来实现.使用 metaclass 可以在创建类时动态修改类定义. 为了使用 metaclass 动态修改类定义,程序需要先定义 me ...
- zabbix-3.4邮件报警
1.开启smtp邮件传输协议 会生成一个授权码后面有用 2.卸载旧版的邮件服务 rpm -qa | grep mailx rpm -qa | grep sendmail rpm -qa | grep ...
- tecplot三维模型绘制二维切片流线
原视频下载地址链接: https://pan.baidu.com/s/1csugHK 密码: xrni
- Momentum Contrast for Unsupervised Visual Representation Learning (MoCo)
Momentum Contrast for Unsupervised Visual Representation Learning 一.Methods Previously Proposed 1. E ...