Skip to content

Commit

Permalink
update rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
byxzone committed Aug 26, 2022
1 parent 530cce9 commit 491d1f1
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 177 deletions.
5 changes: 2 additions & 3 deletions eBPF_Supermarket/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,13 @@ eBPF工具集散地
| 基于 eBPF 的云原生场景下 Pod 性能监测 | cilium_ebpf_probe | 针对云原生领域下的Pod提供进程级别的细粒度监测 | 汪雨薇 |
| 基于 eBPF 的云原生场景下 sidecar 性能监测 | sidecar | 针对云原生场景下 sidecar 的工作原理进行内核层面的观测和优化 | [@ESWZY](https://github.com/ESWZY) |
| 基于 eBPF 的Linux系统性能监测工具-网络子系统 | Linux network subsystem monitoring based on eBPF | 基于eBPF机制对Linux系统网络子系统的TCP层进行性能监测 | [@AnneY](https://github.com/AnneYang720) |
| 基于 eBPF 的 XDP 研究与应用 | Research and application of XDP based on eBPF | 基于eBPF XDP机制打造一个工具使系统性能得到提升 | [@byxzone](https://github.com/byxzone) |
| 基于 eBPF 的 XDP 研究与应用 | XDP_Res-Application | 基于eBPF XDP机制打造一个工具使系统性能得到提升 | [@byxzone](https://github.com/byxzone) |
| | CPU_Subsystem | | |
| | eBPF_DDos | | |
| 基于 eBPF 的 DNS Cache | eBPF_dns_cache | 缓存 DNS 查询结果,并在需要时构造并注入 DNS 响应 | [@7rah](https://github.com/7rah) |
| | CPU_Subsystem | | |
| | Filesystem_Subsystem | | |
| | LSM_BPF | | |
| | Memory_Subsystem | | |
| | XDP_Res-Application | | |

| |

2 changes: 1 addition & 1 deletion eBPF_Supermarket/XDP_Res-Application/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
.vscode
__pycache__
./src/__pycache__
81 changes: 0 additions & 81 deletions eBPF_Supermarket/XDP_Res-Application/docs/design/match.md
Original file line number Diff line number Diff line change
@@ -1,81 +0,0 @@
## 根据五元组信息匹配对应规则

五元组信息定义:

```c
struct metainfo{
u32 ipproto; //协议
u32 saddr; //源ip地址
u32 daddr; //目的ip地址
u16 sport; //源端口号
u16 dport; //目的端口号
};
```

BPF HASH定义(BCC)

```c
BPF_HASH(ipproto_map, u32, u32);
BPF_HASH(saddr_map, u32, u32);
BPF_HASH(daddr_map, u32, u32);
BPF_HASH(sport_map, u16, u32);
BPF_HASH(dport_map, u16, u32);
BPF_HASH(action_map,u32, u32);
```
### 规则预处理
#### 输入
`[IPPROTO,SADDR,DADDR,SPORT,DPORT,ACTION]`
- 对所有ICMP协议的数据包执行DROP
`[“ICMP”,0,0,0,0,”DROP”]`
- 对所有TCP协议且目的端口号为22的数据包执行DROP
`[“TCP”,0,0,0,22,”DROP”]`
#### step 1 规范化处理
- 字符串转换为数字,如”ICMP”转为1,”TCP”转为6(`IPPROTO_ICMP`=1,`IPPROTO_TCP`=6)。”DROP”转为1(`XDP_DROP` = 1)
- 源/目的 ip地址/端口号 从主机字节序转换为网络字节序(`htonl`、`htons`)
#### step 2 合并同类型
- 创建一个hash表,如:
```python
rules_merged = {"ipproto":{},"saddr":{},"daddr":{},"sport":{},"dport":{},"action":{}}
```
- 遍历step 1处理后的每条规则,对规则中的每一项,如`dport`,检查`rules_merged`中是否存在以规则中的`dport`的值对应的key。

若存在,则用该key对应的值与当前规则编号进行**位或(|)**操作。若不存在,则创建一个item,值为当前规则的编号。

- 如果当前项为`0`,如`sport``0`,则把key设置为65535

- 每遍历一次,规则编号左移一位。(`i = i << 1`

### 匹配

- 得到五元组信息后,逐个查找对应map。

- 对结果进行**位与(&)**操作。

- 取出优先级最高的规则(编号小的规则)

```c
result_bit &= -result_bit; // (result_bit &= ~result_bit+1)
```

- 格局规则编号,从`action_map`中找到对应规则

- 若为DROP,则返回`XDP_DROP`
- 若为REDIRECT,则进行下一步处理
- 根据规则编号,查找`redirect_map`
- 修改数据包(包括源/目标 地址/端口),返回`XDP_PASS`继续交给协议栈处理,或者使用`bpf_redirect`返回`XDP_REDIRECT`转发给指定网卡。

### 参考

https://blog.csdn.net/ByteDanceTech/article/details/106632252
2 changes: 0 additions & 2 deletions eBPF_Supermarket/XDP_Res-Application/src/filter.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ static int match_rule(struct metainfo *info){
result_bit = result_bit & *ipproto_bit;
}
}
if(info->dport == 5632)
bpf_trace_printk("1:%d",result_bit);
if(saddr_bit == NULL)
saddr_bit = saddr_map.lookup(&wildcard_u32);
if(saddr_bit != NULL){
Expand Down
112 changes: 29 additions & 83 deletions eBPF_Supermarket/XDP_Res-Application/src/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,88 +5,37 @@

b = BPF(src_file = "filter.bpf.c")

def rules_merge():
def rules_to_map():
rules_list = rules.rule_pretreat(rules.rules_raw)
rules_merged = {"ipproto":{},"saddr":{},"daddr":{},"sport":{},"dport":{},"action":{}}
keys = list(rules_merged.keys())
i = 1
for r in rules_list:
for k in range(0,5):
#print(keys[k],r[k])
if r[k] not in rules_merged[keys[k]]:
rules_merged[keys[k]][r[k]] = i
else:
rules_merged[keys[k]][r[k]] |= i
rules_merged['action'][i] = r[5]
i = i<< 1
for k in range(0,5):
if 65535 in rules_merged[keys[k]]:
for j,v in rules_merged[keys[k]].items():
if j != 65535:
rules_merged[keys[k]][j] &= rules_merged[keys[k]][65535]
print(rules_merged)
return rules_merged

def rules_to_map():
'''
if(r[0] != 0):
ipproto_map_values[i] = ct.c_uint(i)
ipproto_map_keys[i] = ct.c_uint(r[0])
if(r[1] != 0):
saddr_map_values[i] = ct.c_uint(i)
saddr_map_keys[i] = ct.c_uint(r[1])
if(r[2] != 0):
daddr_map_values[i] = ct.c_uint(i)
daddr_map_keys[i] = ct.c_uint(r[2])
if(r[3] != 0):
sport_map_values[i] = ct.c_uint(i)
sport_map_keys[i] = ct.c_ushort(r[3])
if(r[4] != 0):
dport_map_values[i] = ct.c_uint(i)
dport_map_keys[i] = ct.c_ushort(r[4])
action_map_keys[i] = ct.c_uint(i)
action_map_values[i] = ct.c_uint(r[5])
'''
rules_merged = rules_merge()
i = 0
for k,v in rules_merged['ipproto'].items():
ipproto_map_keys[i] = ct.c_uint(k)
ipproto_map_values[i] = ct.c_uint(v)
i += 1
i = 0
for k,v in rules_merged['saddr'].items():
saddr_map_keys[i] = ct.c_uint(k)
saddr_map_values[i] = ct.c_uint(v)
i += 1
i = 0
for k,v in rules_merged['daddr'].items():
daddr_map_keys[i] = ct.c_uint(k)
daddr_map_values[i] = ct.c_uint(v)
i += 1
i = 0
for k,v in rules_merged['sport'].items():
sport_map_keys[i] = ct.c_ushort(k)
sport_map_values[i] = ct.c_uint(v)
i += 1
i = 0
for k,v in rules_merged['dport'].items():
dport_map_keys[i] = ct.c_ushort(k)
dport_map_values[i] = ct.c_uint(v)
i += 1
i = 0
for k,v in rules_merged['action'].items():
action_map_keys[i] = ct.c_uint(k)
action_map_values[i] = ct.c_uint(v)
i += 1
if(r[0] != 0):
ipproto_map_values[i] = ct.c_uint(i)
ipproto_map_keys[i] = ct.c_uint(r[0])
if(r[1] != 0):
saddr_map_values[i] = ct.c_uint(i)
saddr_map_keys[i] = ct.c_uint(r[1])
if(r[2] != 0):
daddr_map_values[i] = ct.c_uint(i)
daddr_map_keys[i] = ct.c_uint(r[2])
if(r[3] != 0):
sport_map_values[i] = ct.c_uint(i)
sport_map_keys[i] = ct.c_ushort(r[3])
if(r[4] != 0):
dport_map_values[i] = ct.c_uint(i)
dport_map_keys[i] = ct.c_ushort(r[4])

action_map_keys[i] = ct.c_uint(i)
action_map_values[i] = ct.c_uint(r[5])

b['ipproto_map'].items_update_batch(ipproto_map_keys,ipproto_map_values)
b['saddr_map'].items_update_batch(saddr_map_keys,saddr_map_values)
b['daddr_map'].items_update_batch(daddr_map_keys,daddr_map_values)
b['sport_map'].items_update_batch(sport_map_keys,sport_map_values)
b['dport_map'].items_update_batch(dport_map_keys,dport_map_values)
b['action_map'].items_update_batch(action_map_keys,action_map_values)
b['ipproto_map'].items_update_batch(ipproto_map_keys,ipproto_map_values)
b['saddr_map'].items_update_batch(saddr_map_keys,saddr_map_values)
b['daddr_map'].items_update_batch(daddr_map_keys,daddr_map_values)
b['sport_map'].items_update_batch(sport_map_keys,sport_map_values)
b['dport_map'].items_update_batch(dport_map_keys,dport_map_values)
b['action_map'].items_update_batch(action_map_keys,action_map_values)

i = i<<1



Expand All @@ -104,23 +53,20 @@ def rules_to_map():
action_map_keys = (b['action_map'].Key * 1024)()
action_map_values = (b['action_map'].Leaf * 1024)()


rules_to_map()

b.attach_xdp(dev="eth0", fn=b.load_func("xdp_filter", BPF.XDP),flags=BPF.XDP_FLAGS_SKB_MODE)
b.attach_xdp(dev="lo", fn=b.load_func("xdp_filter", BPF.XDP),flags=BPF.XDP_FLAGS_SKB_MODE)
print("xdp attached")
print(b['ipproto_map'].items())
print(b['dport_map'].items())
print(b['action_map'].items())

time_count = 0
while 1:
try:
time.sleep(1)
except KeyboardInterrupt:
print("Removing filter from device")
break
time_count += 1
if(time_count == 30):
break


b.remove_xdp("eth0", BPF.XDP_FLAGS_SKB_MODE)
b.remove_xdp("lo", BPF.XDP_FLAGS_SKB_MODE)
Loading

0 comments on commit 491d1f1

Please sign in to comment.