Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */ 2 : : #ifndef __NET_LWTUNNEL_H 3 : : #define __NET_LWTUNNEL_H 1 4 : : 5 : : #include <linux/lwtunnel.h> 6 : : #include <linux/netdevice.h> 7 : : #include <linux/skbuff.h> 8 : : #include <linux/types.h> 9 : : #include <net/route.h> 10 : : 11 : : #define LWTUNNEL_HASH_BITS 7 12 : : #define LWTUNNEL_HASH_SIZE (1 << LWTUNNEL_HASH_BITS) 13 : : 14 : : /* lw tunnel state flags */ 15 : : #define LWTUNNEL_STATE_OUTPUT_REDIRECT BIT(0) 16 : : #define LWTUNNEL_STATE_INPUT_REDIRECT BIT(1) 17 : : #define LWTUNNEL_STATE_XMIT_REDIRECT BIT(2) 18 : : 19 : : enum { 20 : : LWTUNNEL_XMIT_DONE, 21 : : LWTUNNEL_XMIT_CONTINUE, 22 : : }; 23 : : 24 : : 25 : : struct lwtunnel_state { 26 : : __u16 type; 27 : : __u16 flags; 28 : : __u16 headroom; 29 : : atomic_t refcnt; 30 : : int (*orig_output)(struct net *net, struct sock *sk, struct sk_buff *skb); 31 : : int (*orig_input)(struct sk_buff *); 32 : : struct rcu_head rcu; 33 : : __u8 data[0]; 34 : : }; 35 : : 36 : : struct lwtunnel_encap_ops { 37 : : int (*build_state)(struct nlattr *encap, 38 : : unsigned int family, const void *cfg, 39 : : struct lwtunnel_state **ts, 40 : : struct netlink_ext_ack *extack); 41 : : void (*destroy_state)(struct lwtunnel_state *lws); 42 : : int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb); 43 : : int (*input)(struct sk_buff *skb); 44 : : int (*fill_encap)(struct sk_buff *skb, 45 : : struct lwtunnel_state *lwtstate); 46 : : int (*get_encap_size)(struct lwtunnel_state *lwtstate); 47 : : int (*cmp_encap)(struct lwtunnel_state *a, struct lwtunnel_state *b); 48 : : int (*xmit)(struct sk_buff *skb); 49 : : 50 : : struct module *owner; 51 : : }; 52 : : 53 : : #ifdef CONFIG_LWTUNNEL 54 : : void lwtstate_free(struct lwtunnel_state *lws); 55 : : 56 : : static inline struct lwtunnel_state * 57 : : lwtstate_get(struct lwtunnel_state *lws) 58 : : { 59 : : if (lws) 60 : : atomic_inc(&lws->refcnt); 61 : : 62 : : return lws; 63 : : } 64 : : 65 : : static inline void lwtstate_put(struct lwtunnel_state *lws) 66 : : { 67 : : if (!lws) 68 : : return; 69 : : 70 : : if (atomic_dec_and_test(&lws->refcnt)) 71 : : lwtstate_free(lws); 72 : : } 73 : : 74 : : static inline bool lwtunnel_output_redirect(struct lwtunnel_state *lwtstate) 75 : : { 76 : : if (lwtstate && (lwtstate->flags & LWTUNNEL_STATE_OUTPUT_REDIRECT)) 77 : : return true; 78 : : 79 : : return false; 80 : : } 81 : : 82 : : static inline bool lwtunnel_input_redirect(struct lwtunnel_state *lwtstate) 83 : : { 84 : : if (lwtstate && (lwtstate->flags & LWTUNNEL_STATE_INPUT_REDIRECT)) 85 : : return true; 86 : : 87 : : return false; 88 : : } 89 : : 90 : : static inline bool lwtunnel_xmit_redirect(struct lwtunnel_state *lwtstate) 91 : : { 92 : : if (lwtstate && (lwtstate->flags & LWTUNNEL_STATE_XMIT_REDIRECT)) 93 : : return true; 94 : : 95 : : return false; 96 : : } 97 : : 98 : : static inline unsigned int lwtunnel_headroom(struct lwtunnel_state *lwtstate, 99 : : unsigned int mtu) 100 : : { 101 : : if ((lwtunnel_xmit_redirect(lwtstate) || 102 : : lwtunnel_output_redirect(lwtstate)) && lwtstate->headroom < mtu) 103 : : return lwtstate->headroom; 104 : : 105 : : return 0; 106 : : } 107 : : 108 : : int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op, 109 : : unsigned int num); 110 : : int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op, 111 : : unsigned int num); 112 : : int lwtunnel_valid_encap_type(u16 encap_type, 113 : : struct netlink_ext_ack *extack); 114 : : int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len, 115 : : struct netlink_ext_ack *extack); 116 : : int lwtunnel_build_state(u16 encap_type, 117 : : struct nlattr *encap, 118 : : unsigned int family, const void *cfg, 119 : : struct lwtunnel_state **lws, 120 : : struct netlink_ext_ack *extack); 121 : : int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate, 122 : : int encap_attr, int encap_type_attr); 123 : : int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate); 124 : : struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len); 125 : : int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b); 126 : : int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb); 127 : : int lwtunnel_input(struct sk_buff *skb); 128 : : int lwtunnel_xmit(struct sk_buff *skb); 129 : : int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len, 130 : : bool ingress); 131 : : 132 : : static inline void lwtunnel_set_redirect(struct dst_entry *dst) 133 : : { 134 : : if (lwtunnel_output_redirect(dst->lwtstate)) { 135 : : dst->lwtstate->orig_output = dst->output; 136 : : dst->output = lwtunnel_output; 137 : : } 138 : : if (lwtunnel_input_redirect(dst->lwtstate)) { 139 : : dst->lwtstate->orig_input = dst->input; 140 : : dst->input = lwtunnel_input; 141 : : } 142 : : } 143 : : #else 144 : : 145 : : static inline void lwtstate_free(struct lwtunnel_state *lws) 146 : : { 147 : : } 148 : : 149 : : static inline struct lwtunnel_state * 150 : : lwtstate_get(struct lwtunnel_state *lws) 151 : : { 152 : : return lws; 153 : : } 154 : : 155 : : static inline void lwtstate_put(struct lwtunnel_state *lws) 156 : : { 157 : : } 158 : : 159 : : static inline bool lwtunnel_output_redirect(struct lwtunnel_state *lwtstate) 160 : : { 161 : : return false; 162 : : } 163 : : 164 : : static inline bool lwtunnel_input_redirect(struct lwtunnel_state *lwtstate) 165 : : { 166 : : return false; 167 : : } 168 : : 169 : : static inline bool lwtunnel_xmit_redirect(struct lwtunnel_state *lwtstate) 170 : : { 171 : : return false; 172 : : } 173 : : 174 : : static inline void lwtunnel_set_redirect(struct dst_entry *dst) 175 : : { 176 : : } 177 : : 178 : : static inline unsigned int lwtunnel_headroom(struct lwtunnel_state *lwtstate, 179 : : unsigned int mtu) 180 : : { 181 : : return 0; 182 : : } 183 : : 184 : : static inline int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op, 185 : : unsigned int num) 186 : : { 187 : : return -EOPNOTSUPP; 188 : : 189 : : } 190 : : 191 : : static inline int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op, 192 : : unsigned int num) 193 : : { 194 : : return -EOPNOTSUPP; 195 : : } 196 : : 197 : : static inline int lwtunnel_valid_encap_type(u16 encap_type, 198 : : struct netlink_ext_ack *extack) 199 : : { 200 : 0 : NL_SET_ERR_MSG(extack, "CONFIG_LWTUNNEL is not enabled in this kernel"); 201 : : return -EOPNOTSUPP; 202 : : } 203 : : static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len, 204 : : struct netlink_ext_ack *extack) 205 : : { 206 : : /* return 0 since we are not walking attr looking for 207 : : * RTA_ENCAP_TYPE attribute on nexthops. 208 : : */ 209 : : return 0; 210 : : } 211 : : 212 : : static inline int lwtunnel_build_state(u16 encap_type, 213 : : struct nlattr *encap, 214 : : unsigned int family, const void *cfg, 215 : : struct lwtunnel_state **lws, 216 : : struct netlink_ext_ack *extack) 217 : : { 218 : : return -EOPNOTSUPP; 219 : : } 220 : : 221 : : static inline int lwtunnel_fill_encap(struct sk_buff *skb, 222 : : struct lwtunnel_state *lwtstate, 223 : : int encap_attr, int encap_type_attr) 224 : : { 225 : : return 0; 226 : : } 227 : : 228 : : static inline int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate) 229 : : { 230 : : return 0; 231 : : } 232 : : 233 : : static inline struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len) 234 : : { 235 : : return NULL; 236 : : } 237 : : 238 : : static inline int lwtunnel_cmp_encap(struct lwtunnel_state *a, 239 : : struct lwtunnel_state *b) 240 : : { 241 : : return 0; 242 : : } 243 : : 244 : : static inline int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb) 245 : : { 246 : : return -EOPNOTSUPP; 247 : : } 248 : : 249 : : static inline int lwtunnel_input(struct sk_buff *skb) 250 : : { 251 : : return -EOPNOTSUPP; 252 : : } 253 : : 254 : : static inline int lwtunnel_xmit(struct sk_buff *skb) 255 : : { 256 : : return -EOPNOTSUPP; 257 : : } 258 : : 259 : : #endif /* CONFIG_LWTUNNEL */ 260 : : 261 : : #define MODULE_ALIAS_RTNL_LWT(encap_type) MODULE_ALIAS("rtnl-lwt-" __stringify(encap_type)) 262 : : 263 : : #endif /* __NET_LWTUNNEL_H */