12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 21ababebaSDavid Lebrun /* 31ababebaSDavid Lebrun * SR-IPv6 implementation 41ababebaSDavid Lebrun * 51ababebaSDavid Lebrun * Author: 61ababebaSDavid Lebrun * David Lebrun <david.lebrun@uclouvain.be> 71ababebaSDavid Lebrun */ 81ababebaSDavid Lebrun 91ababebaSDavid Lebrun #ifndef _NET_SEG6_H 101ababebaSDavid Lebrun #define _NET_SEG6_H 111ababebaSDavid Lebrun 12915d7e5eSDavid Lebrun #include <linux/net.h> 13915d7e5eSDavid Lebrun #include <linux/ipv6.h> 146c8702c6SDavid Lebrun #include <linux/seg6.h> 150eb71a9dSNeilBrown #include <linux/rhashtable-types.h> 16915d7e5eSDavid Lebrun 171ababebaSDavid Lebrun static inline void update_csum_diff4(struct sk_buff *skb, __be32 from, 181ababebaSDavid Lebrun __be32 to) 191ababebaSDavid Lebrun { 201ababebaSDavid Lebrun __be32 diff[] = { ~from, to }; 211ababebaSDavid Lebrun 221ababebaSDavid Lebrun skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum); 231ababebaSDavid Lebrun } 241ababebaSDavid Lebrun 251ababebaSDavid Lebrun static inline void update_csum_diff16(struct sk_buff *skb, __be32 *from, 261ababebaSDavid Lebrun __be32 *to) 271ababebaSDavid Lebrun { 281ababebaSDavid Lebrun __be32 diff[] = { 291ababebaSDavid Lebrun ~from[0], ~from[1], ~from[2], ~from[3], 301ababebaSDavid Lebrun to[0], to[1], to[2], to[3], 311ababebaSDavid Lebrun }; 321ababebaSDavid Lebrun 331ababebaSDavid Lebrun skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum); 341ababebaSDavid Lebrun } 351ababebaSDavid Lebrun 36915d7e5eSDavid Lebrun struct seg6_pernet_data { 37915d7e5eSDavid Lebrun struct mutex lock; 38915d7e5eSDavid Lebrun struct in6_addr __rcu *tun_src; 39bf355b8dSDavid Lebrun #ifdef CONFIG_IPV6_SEG6_HMAC 40bf355b8dSDavid Lebrun struct rhashtable hmac_infos; 41bf355b8dSDavid Lebrun #endif 42915d7e5eSDavid Lebrun }; 43915d7e5eSDavid Lebrun 44915d7e5eSDavid Lebrun static inline struct seg6_pernet_data *seg6_pernet(struct net *net) 45915d7e5eSDavid Lebrun { 4663526e1cSMathieu Xhonneux #if IS_ENABLED(CONFIG_IPV6) 47915d7e5eSDavid Lebrun return net->ipv6.seg6_data; 4863526e1cSMathieu Xhonneux #else 4963526e1cSMathieu Xhonneux return NULL; 5063526e1cSMathieu Xhonneux #endif 51915d7e5eSDavid Lebrun } 52915d7e5eSDavid Lebrun 53915d7e5eSDavid Lebrun extern int seg6_init(void); 54915d7e5eSDavid Lebrun extern void seg6_exit(void); 556c8702c6SDavid Lebrun extern int seg6_iptunnel_init(void); 566c8702c6SDavid Lebrun extern void seg6_iptunnel_exit(void); 57d1df6fd8SDavid Lebrun extern int seg6_local_init(void); 58d1df6fd8SDavid Lebrun extern void seg6_local_exit(void); 596c8702c6SDavid Lebrun 60bb986a50SAhmed Abdelsalam extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced); 61fa55a7d7SAndrew Lunn extern struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags); 62e4129440SAndrew Lunn extern void seg6_icmp_srh(struct sk_buff *skb, struct inet6_skb_parm *opt); 6332d99d0bSDavid Lebrun extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, 6432d99d0bSDavid Lebrun int proto); 65b04c80d3SDavid Lebrun extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh); 661c1e761eSMathieu Xhonneux extern int seg6_lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr, 671c1e761eSMathieu Xhonneux u32 tbl_id); 68*222a011eSAndrew Lunn 69*222a011eSAndrew Lunn /* If the packet which invoked an ICMP error contains an SRH return 70*222a011eSAndrew Lunn * the true destination address from within the SRH, otherwise use the 71*222a011eSAndrew Lunn * destination address in the IP header. 72*222a011eSAndrew Lunn */ 73*222a011eSAndrew Lunn static inline const struct in6_addr *seg6_get_daddr(struct sk_buff *skb, 74*222a011eSAndrew Lunn struct inet6_skb_parm *opt) 75*222a011eSAndrew Lunn { 76*222a011eSAndrew Lunn struct ipv6_sr_hdr *srh; 77*222a011eSAndrew Lunn 78*222a011eSAndrew Lunn if (opt->flags & IP6SKB_SEG6) { 79*222a011eSAndrew Lunn srh = (struct ipv6_sr_hdr *)(skb->data + opt->srhoff); 80*222a011eSAndrew Lunn return &srh->segments[0]; 81*222a011eSAndrew Lunn } 82*222a011eSAndrew Lunn 83*222a011eSAndrew Lunn return NULL; 84*222a011eSAndrew Lunn } 85*222a011eSAndrew Lunn 86*222a011eSAndrew Lunn 871ababebaSDavid Lebrun #endif 88