blob: af668f17b3988d890fed907a22339cfc1d3fd25c [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
David Lebrun1ababeb2016-11-08 14:57:39 +01002/*
3 * SR-IPv6 implementation
4 *
5 * Author:
6 * David Lebrun <david.lebrun@uclouvain.be>
David Lebrun1ababeb2016-11-08 14:57:39 +01007 */
8
9#ifndef _NET_SEG6_H
10#define _NET_SEG6_H
11
David Lebrun915d7e52016-11-08 14:57:40 +010012#include <linux/net.h>
13#include <linux/ipv6.h>
David Lebrun6c8702c2016-11-08 14:57:41 +010014#include <linux/seg6.h>
NeilBrown0eb71a92018-06-18 12:52:50 +100015#include <linux/rhashtable-types.h>
David Lebrun915d7e52016-11-08 14:57:40 +010016
David Lebrun1ababeb2016-11-08 14:57:39 +010017static inline void update_csum_diff4(struct sk_buff *skb, __be32 from,
18 __be32 to)
19{
20 __be32 diff[] = { ~from, to };
21
22 skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum);
23}
24
25static inline void update_csum_diff16(struct sk_buff *skb, __be32 *from,
26 __be32 *to)
27{
28 __be32 diff[] = {
29 ~from[0], ~from[1], ~from[2], ~from[3],
30 to[0], to[1], to[2], to[3],
31 };
32
33 skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum);
34}
35
David Lebrun915d7e52016-11-08 14:57:40 +010036struct seg6_pernet_data {
37 struct mutex lock;
38 struct in6_addr __rcu *tun_src;
David Lebrunbf355b82016-11-08 14:57:42 +010039#ifdef CONFIG_IPV6_SEG6_HMAC
40 struct rhashtable hmac_infos;
41#endif
David Lebrun915d7e52016-11-08 14:57:40 +010042};
43
44static inline struct seg6_pernet_data *seg6_pernet(struct net *net)
45{
Mathieu Xhonneux63526e12018-05-20 14:58:12 +010046#if IS_ENABLED(CONFIG_IPV6)
David Lebrun915d7e52016-11-08 14:57:40 +010047 return net->ipv6.seg6_data;
Mathieu Xhonneux63526e12018-05-20 14:58:12 +010048#else
49 return NULL;
50#endif
David Lebrun915d7e52016-11-08 14:57:40 +010051}
52
53extern int seg6_init(void);
54extern void seg6_exit(void);
David Lebrun6c8702c2016-11-08 14:57:41 +010055extern int seg6_iptunnel_init(void);
56extern void seg6_iptunnel_exit(void);
David Lebrund1df6fd2017-08-05 12:38:26 +020057extern int seg6_local_init(void);
58extern void seg6_local_exit(void);
David Lebrun6c8702c2016-11-08 14:57:41 +010059
Ahmed Abdelsalambb986a52020-06-03 06:54:42 +000060extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced);
Andrew Lunnfa55a7d2022-01-03 18:11:30 +010061extern struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags);
Andrew Lunne4129442022-01-03 18:11:31 +010062extern void seg6_icmp_srh(struct sk_buff *skb, struct inet6_skb_parm *opt);
David Lebrun32d99d02017-08-25 09:56:44 +020063extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
64 int proto);
David Lebrunb04c80d2017-08-05 12:38:25 +020065extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
Mathieu Xhonneux1c1e7612018-05-20 14:58:13 +010066extern int seg6_lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
67 u32 tbl_id);
Andrew Lunn222a0112022-01-03 18:11:32 +010068
69/* If the packet which invoked an ICMP error contains an SRH return
70 * the true destination address from within the SRH, otherwise use the
71 * destination address in the IP header.
72 */
73static inline const struct in6_addr *seg6_get_daddr(struct sk_buff *skb,
74 struct inet6_skb_parm *opt)
75{
76 struct ipv6_sr_hdr *srh;
77
78 if (opt->flags & IP6SKB_SEG6) {
79 srh = (struct ipv6_sr_hdr *)(skb->data + opt->srhoff);
80 return &srh->segments[0];
81 }
82
83 return NULL;
84}
85
86
David Lebrun1ababeb2016-11-08 14:57:39 +010087#endif