-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First working prototype - DHCPv4 #11
base: main
Are you sure you want to change the base?
Conversation
Built-in memcpy and memset functions cause verifier to complain about misaligned stack access. To get around that (and be able to copy a dynamic number of bytes via memcpy), two custom functions are added. This version of the relay uses interface name + VLAN identifiers in option 82 circuit ID (left-aligned, length IF_NAMESIZE with trailing null bytes). Signed-off-by: Yoel Caspersen <[email protected]>
When allowing packets with 1 VLAN tag only, verifier complains about BPF program being too large. Compiled with LLVM 13. Signed-off-by: Yoel Caspersen <[email protected]>
In this version of the relay, we assume that client requests are received on a double tagged VLAN interface and server replies are received on a single tagged VLAN interface. Test scripts are added: - test.sh (configures BNG and sets L3 config) - cleanup_test.sh (removes BNG configuration) - trace.sh (opens trace pipe for debugging) The code for adding interface name is disabled because it makes the verifier complain about the BPF program being too large. To-do: - Fix verifier issue to include interface name in option 82 - For server replies, erase option 82 instead of (partial) overwrite Signed-off-by: Yoel Caspersen <[email protected]>
This version works with kernel 5.15 and LLVM 13. Improvements: - Interface name is added to Option 82 Circuit ID - On server replies, Option 82 is wiped completely - Char array parameters replaced with structs Functions that previously used char arrays as function parameters now use structs instead - otherwise the verifier cannot perform proper boundary checks. To-do: - IPv6 support - Multiple interface support Signed-off-by: Yoel Caspersen <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job getting something to work! Unfortunately the code has turned a wee bit spaghetti in the process; I guess most of the comments below could be summed up as changes that fix that :)
dhcp-relay/dhcp-relay.h
Outdated
@@ -38,6 +43,11 @@ struct dhcp_option_255 { | |||
__u8 t; | |||
}; | |||
|
|||
struct dev_name { | |||
char name[IF_NAMESIZE]; | |||
__u8 len; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
len is unneeded, see below
dhcp-relay/dhcp_kern_xdp.c
Outdated
} | ||
|
||
if (i > 0) { | ||
opt->val[--i] = '.'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function is called u16_to_ascii
, so what is this doing here? Better leave this to the caller.
dhcp-relay/dhcp_kern_xdp.c
Outdated
} | ||
|
||
if (i > RAI_OPTION_LEN) | ||
return -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is not needed...
} | ||
/* Adjust IP offset for VLAN header when VLAN header has been added */ | ||
if (head_adjusted) { | ||
ip = data + ip_offset + sizeof (struct vlan_hdr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why carry this head_adjusted
all the way down here instead of just modifying ip_offset
directly when doing the adjustment?
return XDP_ABORTED; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary braces
@@ -499,7 +685,6 @@ int xdp_dhcp_relay(struct xdp_md *ctx) { | |||
/* Re-calculate ip checksum */ | |||
__u32 sum = calc_ip_csum(&oldip, ip, oldip.check); | |||
ip->check = ~sum; | |||
rc = XDP_PASS; | |||
|
|||
goto out; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant goto
@@ -499,7 +685,6 @@ int xdp_dhcp_relay(struct xdp_md *ctx) { | |||
/* Re-calculate ip checksum */ | |||
__u32 sum = calc_ip_csum(&oldip, ip, oldip.check); | |||
ip->check = ~sum; | |||
rc = XDP_PASS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above; this is actually the right place to change the return code back into something that sends out the packet, as this is where the packet is once again valid...
OUTER_VLAN=83 | ||
INNER_VLAN=20 | ||
UPLINK_VLAN=84 | ||
IF="ens6f0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be possible to test this using network namespaces; having a test that is runnable without needing special hardware makes it way easier to test. Such a test should really be added so it can be run as part of a CI job.
This makes several changes to improve the readability of write_dhcp_option_82(): The main change is in reworking the string helpers to be smaller and more modular, and using a separate buffer for stringifying the VLAN tags before copying them to the DHCP option field. Get rid of str_len() and the len member of struct dev_name. To aid in this, the whole containing function is made global (i.e., a separate BPF subprog) instead of the helpers. In addition, the local variables are renamed to be more descriptive, and the option struct is initialised using struct initialisation syntax. Signed-off-by: Toke Høiland-Jørgensen <[email protected]>
The case statements of the option parsing 'switch' had grown an extra level of indentation. Get rid of that. Signed-off-by: Toke Høiland-Jørgensen <[email protected]>
Add a -v option to turn on verbose logging in libbpf; this makes it possible to see which relocations libbpf is making, which is useful to see which functions get turned into separate sub functions. Signed-off-by: Toke Høiland-Jørgensen <[email protected]>
Took the liberty of fixing some of the issues I pointed out myself, and pushed them to your branch :) |
This version works with kernel 5.15 and LLVM 13.
Improvements:
Functions that previously used char arrays as function parameters now
use structs instead - otherwise the verifier cannot perform proper
boundary checks.
To-do: