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。

  1. 从Device接收Packet交给事先注册的event handler进行处理
  2. 接收Packet后识别是否是unknown packet,是则交由upcall处理
  3. vswitchd对unknown packet找到flow rule进行处理
  4. 将Flow rule发送给datapath

    也就是说OVS处理数据包首先会看有没有事先订阅的事件,如果有直接转交给该对应的处理函数,然后匹配流表,最后按照传统网络协议栈进行处理。

ovs 数据包的处理过程的更多相关文章

  1. Linux内核--网络栈实现分析(七)--数据包的传递过程(下)

    本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7545855 更多请查看专栏,地 ...

  2. Linux内核--网络栈实现分析(二)--数据包的传递过程--转

    转载地址http://blog.csdn.net/yming0221/article/details/7492423 作者:闫明 本文分析基于Linux Kernel 1.2.13 注:标题中的”(上 ...

  3. [转]Linux网络 - 数据包的发送过程

    转, 原文:https://segmentfault.com/a/1190000008926093 -------------------------------------------------- ...

  4. Linux内核--网络栈实现分析(二)--数据包的传递过程(上)

    本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7492423 更多请看专栏,地址 ...

  5. Linux网络 - 数据包的接收过程【转】

    转自:https://segmentfault.com/a/1190000008836467 本文将介绍在Linux系统中,数据包是如何一步一步从网卡传到进程手中的. 如果英文没有问题,强烈建议阅读后 ...

  6. [转]Linux网络 - 数据包的接收过程

    转, 原文: https://segmentfault.com/a/1190000008836467 ------------------------------------------------- ...

  7. CCNA - Part10 数据包的通信过程

    这篇文章主要是对数据包在同网段和不同网段的转发流程梳理,使用 ping 命令进行实际抓包测试. 网关的概念: 对于像 PC 等终端设备来说,通过交换机可以实现同网段的通信.但如果想要给其他网段发生数据 ...

  8. opencontrail—VXLAN模式下数据包的传输过程

    在这篇文章中,我们将看到VM生成的数据包如何能够到达另一个VM或外部资源,Neutron使用OpenContrail插件的上下文中的关键概念/组件是什么. 我们将重点介绍OpenContrail,它如 ...

  9. Linux网络 - 数据包的接收过程(转)

    https://segmentfault.com/a/1190000008836467

随机推荐

  1. Intel 80386 CPU

    一.80386 概述 80386处理器被广泛应用在1980年代中期到1990年代中期的IBM PC相容机中.这些PC机称为「80386电脑」或「386电脑」,有时也简称「80386」或「386」.80 ...

  2. __try __except与__try __finally的嵌套使用以及__finally的调用时机

    原文:https://blog.csdn.net/SwordArcher/article/details/82465522 try-finally语句的语法与try-except很类似,稍有不同的是, ...

  3. tar归档压缩命令和zip归档 和7zip压缩命令;库文件归档ar命令

    第一.tar 归档 tar -c 创建归档文件包 tar -x 释放归档文件包 tar -t 查看归档文件包 tar -v 显示归档包操作过程信息 tar -f 指定归档文件名 案例1:归档 /hom ...

  4. 【一起来烧脑】一步学会AngularJS系统

    AngularJS是一个JavaScript框架 一个用JavaScript编写的库 [外链图片转存失败(img-JUTh171K-1563341248796)(https://upload-imag ...

  5. 64位内核开发第十二讲,进程监视,ring3跟ring0事件同步.

    一丶同步与互斥详解,以及实现一个进程监视软件. 1.用于线程同步的 KEVENT 事件很简单分别分为 事件状态. 以及事件类别. 事件状态: 有信号 Signaled 无信号 Non-signaled ...

  6. Sublime Text 3 import Anaconda 无法正常补全模块名解决办法

    Sublime Text 3 Anaconda配置 在安装Sublime Text3之后我们总会安装一些插件,比如Python的Anaconda自动补全插件.但是,装好之后发现import 时无法像别 ...

  7. 项目发布到tomcat后,通过项目名称访问报404

    查看tomcat发布地址发现和项目名称不一致 如果直接拷贝项目,可能也需要修改此选项 解决方案: 经过排查发现了原因: 首先说明一下项目 Maven+SSM 需要使用到 maven tomcat 7 ...

  8. NOIP(划掉)CSP2019一轮知识点

    今年似乎变动很大呢…… 去年总结的 历年真题 以下标题中打*的是我认为的重点内容 *一.关于计算机 (一)计算机组成 计算机的工作原理跟人的大脑很相似,而且还是大脑功能的延伸,所以习惯上叫它电脑. 硬 ...

  9. 【CSP模拟赛】益智游戏(最短路(DJSPFA)&拓扑排序)

    题目描述 小P和小R在玩一款益智游戏.游戏在一个正权有向图上进行. 小P 控制的角色要从A 点走最短路到B 点,小R 控制的角色要从C 点走最短路到D 点. 一个玩家每回合可以有两种选择,移动到一个相 ...

  10. django celery 异步执行任务遇到的坑

    部署后,任务没有持久化,所有用supervisor 进行进程管理 安装 pip install supervisor 创建 配置文件 [program:testplatform-flower] com ...