bfp 在内核运行的核心入口函数及其变形

bpf prog内核运行核心入口函数

总结:___bpf_prog_run

bfp 在内核运行的核心入口函数:___bpf_prog_run
___bpf_prog_run是bfp的核心函数入口,该函数被多个不同stack size的函数调用。
函数指针数组interpreters这把上面的这些函数汇集到一起。
当bpf程序被加载到内核时候,内核创建为它一个bpf_prog结构体,根据prog的stacksize,选择对应的interpreters里的对应的
函数,并保存到bpf_prog里的bpf_func上。
这样后续hook点运行bpf_prog程序时候,就使用bpf_func运行。

Read More

xdp 是如何加载到内核并运行的

XDP framework

xdp在内核里的有三个关键步骤:

  • load: 加载到内核
  • attach: 绑定到一个网口
  • run:网口收包时候,调用并执行bpf prog

load加载: 通过ebpf系统调用, 把prog加载到内核

fd = sys_bpf(BPF_PROG_LOAD, attr, size);

  • 在内核里创建一个bfp_prog结构体用以存储bpf prog。
  • 通过bpf_check检查prog程序的安全性和合法性。
  • 通过bpf_prog_select_runtime指定bpf prog对应的执行函数
  • 这个函数指针保存在bpf_func这个字段里。这里的function最终指向通用的bfp run函数___bpf_prog_run
    关于___bpf_prog_run这个具体封装和实现见另外一篇文章。

attach绑定: 将prog程序绑定到一个特定的网口的struct net_device

libpf函数do_attach将上一步加载在内核里的prog跟一个网口绑定, 具体实现是通过下发netlink命令。
这是个generic类型的netlink命令,最终通过dev_change_xdp_fd将prog挂载到对应netdev下面。

Read More

how tcpdump work with vlan filter

  • 问题描述:
    tcpdump在网口抓包和读取pcap文件,相同的filter表达式”icmp“,对vlan报文有不同的处理结果。
    在网口上抓包可以看到vlan和非vlan两种流量, 而读取pcap只能看到非vlan流量一种流量。

  • 原因:
    kernel里在tcpdump抓包之前会把报文的vlan提前解析掉,并把vlan信息放到skb的metadata里了。
    所以tcpdump(内核的af_packet对应的ptype_all)处理的报文都是不带vlan的,因此这两类报文都会被过滤出来。
    而读取pcap时候,因为vlan报文并没有被剥离掉,所以vlan报文不满足过滤条件,被丢弃了。

国外已经有人发现并分析过这个问题
https://andreaskaris.github.io/blog/networking/bpf-and-tcpdump/

Read More

xfrm: configure xfrm state and policy with iproute2

测试环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ip netns exec ns1 ip l s veth1 down
ip l delete veth0
ip netns delete ns1

ip l add type veth
ip netns add ns1

ip l s dev veth1 netns ns1
ip l set veth0 up
ip netns exec ns1 ip l set veth1 up

ip a a dev veth0 192.168.100.1/24
ip netns exec ns1 ip a a dev veth1 192.168.100.2/24
ip netns exec ns1 ip r a default via 192.168.100.1

Read More

fib: how ipv4 lookup route with rule route

概述

规则路由(rule route)

这部分详见ip rule命令帮助手册,
https://man7.org/linux/man-pages/man8/ip-rule.8.html
简要总结:

  • 支持多种形式的路由查找,不再仅仅局限于根据目的地址查找一种模式。
  • rule route采用了类似match-action模式, 不过rule route称之为SELECTORACTION
  • SELECTOR 支持多种形式,比如IP、PORT、进出网口、tos以及非操作(not)
  • ACTION 中几个重要的类型:
    • table:到指定的TABLE_ID对应的路由表里查找(所以这里要求必须支持多table)
    • nat: 支持IP地址nat
    • goto: 跳转到指定的rule route,通过这个可以做成多级级联。

几点说明

优先级

rule route是支持优先级的。 通过 ip rule show命令我们可以看到每条rule对应的优先级。添加rule时候,默认的是当前除0以外最高优先级的值-1, 即默认新建的rule优先级高。

Read More

tcpdump and ebpf

以内核v6.6代码,介绍tcpdump程序如何与内核交互,加载bpf程序的。

加载:

libpcap通过sockopt里的“SO_ATTACH_FILTER“,
在 packet socket下的”sk_filter“挂载prog呈现。

运行:

当skb报文到达packet_rcv时候, 通过调用___bpf_prog_run函数(注意,这个函数是3个下滑线,区别于2个下划线的函数)
运行”sk_filter“对应的prog。
其中prog的
==>packet_rcv
==> ==> run_filter
==> ==> ==>bpf_prog_run_clear_cb

Read More

how tcpdump work with cbpf

tcpdump通过libpcap库以及内核的af_packet对数据包问题进行抓取。
关于这两部分的如何协作抓包,之前blog里已经写过。
这里主要记录分析,在ebpf之前的内核(以v3.0)如何处理tcpdump里的filter的。

filter编译后,如何加载到内核里的:

在filter被翻译为一系列的指令后,这个指令buff被libpcap,
通过sockopt里的SO_ATTACH_FILTE选项,
最终挂载到AF_PACKET socket下的sk_filter上。

Read More

How IPv6 addresses are flushed on link down

IPv6协议栈里, 当一个网口被down之后,网口上对应的IP地址也会一起被flush掉。
面对IPv6跟IPv4不同的行为方式,内核提供了一个规避的开关。
在4.6内核之后提供了一个开关,用来避免IPv6地址别清理掉。
这个开关既有全局的设置,也有每个interface粒度的单独开关。

Read More

内核OVS的学习总结


OVS里最重要的几个元素:vport,flow,datapath。
其中datapth是vport和flow的桥梁。

kernel ovs 核心结构体及其关联

VPORT

内核包含多个datapath(brige),上面包含一个或者多个vport。
其中一个VPORT表示一个端口,一个vport只能归于一个特定的datapath。
每个vport有自己的type, 对应不同的vport ops.
每个内核网口被注册为vport的时候。

Read More