Message ID | 20211201202519.3637005-4-andrew@lunn.ch (mailing list archive) |
---|---|
State | RFC |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Fix traceroute in the presence of SRv6 | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Clearly marked for net-next |
netdev/fixes_present | success | Fixes tag not required for -next series |
netdev/subject_prefix | success | Link |
netdev/cover_letter | success | Series has a cover letter |
netdev/patch_count | success | Link |
netdev/header_inline | success | No static functions without inline keyword in header files |
netdev/build_32bit | success | Errors and warnings before: 0 this patch: 0 |
netdev/cc_maintainers | success | CCed 5 of 5 maintainers |
netdev/build_clang | success | Errors and warnings before: 0 this patch: 0 |
netdev/module_param | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Signed-off-by tag matches author and committer |
netdev/verify_fixes | success | No Fixes tag |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 0 this patch: 0 |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 25 lines checked |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/source_inline | success | Was 0 now: 0 |
On 12/1/21 1:25 PM, Andrew Lunn wrote: > @@ -563,12 +564,18 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, > const struct in6_addr *saddr = &hdr->saddr; > const struct in6_addr *daddr = &hdr->daddr; > struct udphdr *uh = (struct udphdr *)(skb->data+offset); > + struct ipv6_sr_hdr *srh; > bool tunnel = false; > struct sock *sk; > int harderr; > int err; > struct net *net = dev_net(skb->dev); > > + if (opt->flags & IP6SKB_SEG6) { > + srh = (struct ipv6_sr_hdr *)(skb->data + opt->srhoff); > + daddr = &srh->segments[0]; > + } > + > sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source, > inet6_iif(skb), inet6_sdif(skb), udptable, NULL); > similarly for this one, have a helper in seg6.h that returns in6_addr pointer. It will be referencing within skb->data so should be fine.
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 6a0e569f0bb8..6a2288e7ddda 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -40,6 +40,7 @@ #include <net/transp_v6.h> #include <net/ip6_route.h> #include <net/raw.h> +#include <net/seg6.h> #include <net/tcp_states.h> #include <net/ip6_checksum.h> #include <net/ip6_tunnel.h> @@ -563,12 +564,18 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, const struct in6_addr *saddr = &hdr->saddr; const struct in6_addr *daddr = &hdr->daddr; struct udphdr *uh = (struct udphdr *)(skb->data+offset); + struct ipv6_sr_hdr *srh; bool tunnel = false; struct sock *sk; int harderr; int err; struct net *net = dev_net(skb->dev); + if (opt->flags & IP6SKB_SEG6) { + srh = (struct ipv6_sr_hdr *)(skb->data + opt->srhoff); + daddr = &srh->segments[0]; + } + sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source, inet6_iif(skb), inet6_sdif(skb), udptable, NULL);
When finding the socket to report an error on, if the invoking packet is using Segment Routing, the IPv6 destination address is that of an intermediate router, not the end destination. Extract the ultimate destination address from the segment address. This change allows traceroute to function in the presence of Segment Routing. Signed-off-by: Andrew Lunn <andrew@lunn.ch> --- net/ipv6/udp.c | 7 +++++++ 1 file changed, 7 insertions(+)