xref: /linux/include/net/seg6.h (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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 
update_csum_diff4(struct sk_buff * skb,__be32 from,__be32 to)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 
update_csum_diff16(struct sk_buff * skb,__be32 * from,__be32 * to)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 
seg6_pernet(struct net * net)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);
55*a79d8fe2SHangbin Liu #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
566c8702c6SDavid Lebrun extern int seg6_iptunnel_init(void);
576c8702c6SDavid Lebrun extern void seg6_iptunnel_exit(void);
58d1df6fd8SDavid Lebrun extern int seg6_local_init(void);
59d1df6fd8SDavid Lebrun extern void seg6_local_exit(void);
60*a79d8fe2SHangbin Liu #else
seg6_iptunnel_init(void)61*a79d8fe2SHangbin Liu static inline int seg6_iptunnel_init(void) { return 0; }
seg6_iptunnel_exit(void)62*a79d8fe2SHangbin Liu static inline void seg6_iptunnel_exit(void) {}
seg6_local_init(void)63*a79d8fe2SHangbin Liu static inline int seg6_local_init(void) { return 0; }
seg6_local_exit(void)64*a79d8fe2SHangbin Liu static inline void seg6_local_exit(void) {}
65*a79d8fe2SHangbin Liu #endif
666c8702c6SDavid Lebrun 
67bb986a50SAhmed Abdelsalam extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced);
68fa55a7d7SAndrew Lunn extern struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags);
69e4129440SAndrew Lunn extern void seg6_icmp_srh(struct sk_buff *skb, struct inet6_skb_parm *opt);
7032d99d0bSDavid Lebrun extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
7132d99d0bSDavid Lebrun 			     int proto);
72b04c80d3SDavid Lebrun extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
731c1e761eSMathieu Xhonneux extern int seg6_lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
741c1e761eSMathieu Xhonneux 			       u32 tbl_id);
75222a011eSAndrew Lunn 
76222a011eSAndrew Lunn /* If the packet which invoked an ICMP error contains an SRH return
77222a011eSAndrew Lunn  * the true destination address from within the SRH, otherwise use the
78222a011eSAndrew Lunn  * destination address in the IP header.
79222a011eSAndrew Lunn  */
seg6_get_daddr(struct sk_buff * skb,struct inet6_skb_parm * opt)80222a011eSAndrew Lunn static inline const struct in6_addr *seg6_get_daddr(struct sk_buff *skb,
81222a011eSAndrew Lunn 						    struct inet6_skb_parm *opt)
82222a011eSAndrew Lunn {
83222a011eSAndrew Lunn 	struct ipv6_sr_hdr *srh;
84222a011eSAndrew Lunn 
85222a011eSAndrew Lunn 	if (opt->flags & IP6SKB_SEG6) {
86222a011eSAndrew Lunn 		srh = (struct ipv6_sr_hdr *)(skb->data + opt->srhoff);
87222a011eSAndrew Lunn 		return  &srh->segments[0];
88222a011eSAndrew Lunn 	}
89222a011eSAndrew Lunn 
90222a011eSAndrew Lunn 	return NULL;
91222a011eSAndrew Lunn }
92222a011eSAndrew Lunn 
93222a011eSAndrew Lunn 
941ababebaSDavid Lebrun #endif
95