struct veth_configuration { char local_veth[VETH_NAME_MAX_LEN]; /* Interface in main namespace */ char remote_veth[VETH_NAME_MAX_LEN]; /* Peer interface in dedicated namespace*/ charnamespace[NS_NAME_MAX_LEN]; /* Namespace for the remote veth */ int next_veth; /* Local interface to redirect traffic to */ char remote_addr[IP_MAX_LEN]; /* IP address of the remote veth */
};
struct prog_configuration { char local_name[PROG_NAME_MAX_LEN]; /* BPF prog to attach to local_veth */ char remote_name[PROG_NAME_MAX_LEN]; /* BPF prog to attach to remote_veth */
u32 local_flags; /* XDP flags to use on local_veth */
u32 remote_flags; /* XDP flags to use on remote_veth */
};
for (i = 0; i < nb_obj; i++) {
local_prog = bpf_object__find_program_by_name(objs[i], prog[index].local_name); if (local_prog) break;
} if (!ASSERT_OK_PTR(local_prog, "find local program")) return -1;
for (i = 0; i < nb_obj; i++) {
remote_prog = bpf_object__find_program_by_name(objs[i], prog[index].remote_name); if (remote_prog) break;
} if (!ASSERT_OK_PTR(remote_prog, "find remote program")) return -1;
interface = if_nametoindex(net_config->veth_cfg[index].local_veth); if (!ASSERT_NEQ(interface, 0, "non zero interface index")) return -1;
ret = bpf_xdp_attach(interface, bpf_program__fd(local_prog),
prog[index].local_flags, NULL); if (!ASSERT_OK(ret, "attach xdp program to local veth")) return -1;
nstoken = open_netns(net_config->veth_cfg[index].namespace); if (!ASSERT_OK_PTR(nstoken, "switch to remote veth namespace")) return -1;
interface = if_nametoindex(net_config->veth_cfg[index].remote_veth); if (!ASSERT_NEQ(interface, 0, "non zero interface index")) {
close_netns(nstoken); return -1;
}
ret = bpf_xdp_attach(interface, bpf_program__fd(remote_prog),
prog[index].remote_flags, NULL); if (!ASSERT_OK(ret, "attach xdp program to remote veth")) {
close_netns(nstoken); return -1;
}
close_netns(nstoken); return 0;
}
staticint create_network(struct net_configuration *net_config)
{ struct nstoken *nstoken = NULL; int i, err;
/* Create unique namespaces */
err = append_tid(net_config->ns0_name, NS_NAME_MAX_LEN); if (!ASSERT_OK(err, "append TID to ns0 name")) goto fail;
SYS(fail, "ip netns add %s", net_config->ns0_name);
for (i = 0; i < VETH_PAIRS_COUNT; i++) {
err = append_tid(net_config->veth_cfg[i].namespace, NS_NAME_MAX_LEN); if (!ASSERT_OK(err, "append TID to ns name")) goto fail;
SYS(fail, "ip netns add %s", net_config->veth_cfg[i].namespace);
}
for (i = 0; i < VETH_PAIRS_COUNT; i++) {
SYS(fail, "ip link add %s type veth peer name %s netns %s",
net_config->veth_cfg[i].local_veth, net_config->veth_cfg[i].remote_veth,
net_config->veth_cfg[i].namespace);
SYS(fail, "ip link set dev %s up", net_config->veth_cfg[i].local_veth); if (net_config->veth_cfg[i].remote_addr[0])
SYS(fail, "ip -n %s addr add %s/24 dev %s",
net_config->veth_cfg[i].namespace,
net_config->veth_cfg[i].remote_addr,
net_config->veth_cfg[i].remote_veth);
SYS(fail, "ip -n %s link set dev %s up", net_config->veth_cfg[i].namespace,
net_config->veth_cfg[i].remote_veth);
}
close_netns(nstoken); return 0;
fail:
close_netns(nstoken); return -1;
}
staticvoid cleanup_network(struct net_configuration *net_config)
{ int i;
SYS_NOFAIL("ip netns del %s", net_config->ns0_name); for (i = 0; i < VETH_PAIRS_COUNT; i++)
SYS_NOFAIL("ip netns del %s", net_config->veth_cfg[i].namespace);
}
xdp_dummy = xdp_dummy__open_and_load(); if (!ASSERT_OK_PTR(xdp_dummy, "xdp_dummy__open_and_load")) return;
xdp_tx = xdp_tx__open_and_load(); if (!ASSERT_OK_PTR(xdp_tx, "xdp_tx__open_and_load")) goto destroy_xdp_dummy;
xdp_redirect_map = xdp_redirect_map__open_and_load(); if (!ASSERT_OK_PTR(xdp_redirect_map, "xdp_redirect_map__open_and_load")) goto destroy_xdp_tx;
if (!ASSERT_OK(create_network(&net_config), "create network")) goto destroy_xdp_redirect_map;
/* Then configure the redirect map and attach programs to interfaces */
map_fd = bpf_map__fd(xdp_redirect_map->maps.tx_port); if (!ASSERT_OK_FD(map_fd, "open redirect map")) goto destroy_xdp_redirect_map;
nstoken = open_netns(net_config.ns0_name); if (!ASSERT_OK_PTR(nstoken, "open NS0")) goto destroy_xdp_redirect_map;
for (i = 0; i < VETH_PAIRS_COUNT; i++) { int next_veth = net_config.veth_cfg[i].next_veth; int interface_id; int err;
interface_id = if_nametoindex(net_config.veth_cfg[next_veth].local_veth); if (!ASSERT_NEQ(interface_id, 0, "non zero interface index")) goto destroy_xdp_redirect_map;
err = bpf_map_update_elem(map_fd, &i, &interface_id, BPF_ANY); if (!ASSERT_OK(err, "configure interface redirection through map")) goto destroy_xdp_redirect_map; if (attach_programs_to_veth_pair(bpf_objs, VETH_REDIRECT_SKEL_NB,
&net_config, ping_config, i)) goto destroy_xdp_redirect_map;
}
/* Test: if all interfaces are properly configured, we must be able to ping * veth33 from veth11
*/
ASSERT_OK(SYS_NOFAIL("ip netns exec %s ping -c 1 -W 1 %s > /dev/null",
net_config.veth_cfg[0].namespace, IP_DST), "ping");
for (i = 0; i < VETH_PAIRS_COUNT; i++) {
err = bpf_map_lookup_elem(cnt_map, &i, &cnt); if (!ASSERT_OK(err, "get IP cnt")) goto destroy_xdp_redirect_map;
if (redirect_flags & BPF_F_EXCLUDE_INGRESS) /* veth11 shouldn't receive the ICMP requests; * others should
*/
ASSERT_EQ(cnt, i ? 4 : 0, "compare IP cnt"); else /* All remote veth should receive the ICMP requests */
ASSERT_EQ(cnt, 4, "compare IP cnt");
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.