13b49e2e9SPablo Neira Ayuso #ifndef _NF_FLOW_TABLE_H 23b49e2e9SPablo Neira Ayuso #define _NF_FLOW_TABLE_H 33b49e2e9SPablo Neira Ayuso 4ac2a6666SPablo Neira Ayuso #include <linux/in.h> 5ac2a6666SPablo Neira Ayuso #include <linux/in6.h> 6ac2a6666SPablo Neira Ayuso #include <linux/netdevice.h> 70eb71a9dSNeilBrown #include <linux/rhashtable-types.h> 8ac2a6666SPablo Neira Ayuso #include <linux/rcupdate.h> 9a1b2f04eSJeremy Sowden #include <linux/netfilter.h> 10af81f9e7SFelix Fietkau #include <linux/netfilter/nf_conntrack_tuple_common.h> 118bb69f3bSPablo Neira Ayuso #include <net/flow_offload.h> 12ac2a6666SPablo Neira Ayuso #include <net/dst.h> 133b49e2e9SPablo Neira Ayuso 143b49e2e9SPablo Neira Ayuso struct nf_flowtable; 15c29f74e0SPablo Neira Ayuso struct nf_flow_rule; 16c29f74e0SPablo Neira Ayuso struct flow_offload; 17c29f74e0SPablo Neira Ayuso enum flow_offload_tuple_dir; 183b49e2e9SPablo Neira Ayuso 199c26ba9bSPaul Blakey struct nf_flow_key { 209c26ba9bSPaul Blakey struct flow_dissector_key_meta meta; 219c26ba9bSPaul Blakey struct flow_dissector_key_control control; 229c26ba9bSPaul Blakey struct flow_dissector_key_basic basic; 239c26ba9bSPaul Blakey union { 249c26ba9bSPaul Blakey struct flow_dissector_key_ipv4_addrs ipv4; 259c26ba9bSPaul Blakey struct flow_dissector_key_ipv6_addrs ipv6; 269c26ba9bSPaul Blakey }; 279c26ba9bSPaul Blakey struct flow_dissector_key_tcp tcp; 289c26ba9bSPaul Blakey struct flow_dissector_key_ports tp; 299c26ba9bSPaul Blakey } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */ 309c26ba9bSPaul Blakey 319c26ba9bSPaul Blakey struct nf_flow_match { 329c26ba9bSPaul Blakey struct flow_dissector dissector; 339c26ba9bSPaul Blakey struct nf_flow_key key; 349c26ba9bSPaul Blakey struct nf_flow_key mask; 359c26ba9bSPaul Blakey }; 369c26ba9bSPaul Blakey 379c26ba9bSPaul Blakey struct nf_flow_rule { 389c26ba9bSPaul Blakey struct nf_flow_match match; 399c26ba9bSPaul Blakey struct flow_rule *rule; 409c26ba9bSPaul Blakey }; 419c26ba9bSPaul Blakey 423b49e2e9SPablo Neira Ayuso struct nf_flowtable_type { 433b49e2e9SPablo Neira Ayuso struct list_head list; 443b49e2e9SPablo Neira Ayuso int family; 45a268de77SFelix Fietkau int (*init)(struct nf_flowtable *ft); 468bb69f3bSPablo Neira Ayuso int (*setup)(struct nf_flowtable *ft, 478bb69f3bSPablo Neira Ayuso struct net_device *dev, 488bb69f3bSPablo Neira Ayuso enum flow_block_command cmd); 49c29f74e0SPablo Neira Ayuso int (*action)(struct net *net, 50c29f74e0SPablo Neira Ayuso const struct flow_offload *flow, 51c29f74e0SPablo Neira Ayuso enum flow_offload_tuple_dir dir, 52c29f74e0SPablo Neira Ayuso struct nf_flow_rule *flow_rule); 53b408c5b0SPablo Neira Ayuso void (*free)(struct nf_flowtable *ft); 543b49e2e9SPablo Neira Ayuso nf_hookfn *hook; 553b49e2e9SPablo Neira Ayuso struct module *owner; 563b49e2e9SPablo Neira Ayuso }; 573b49e2e9SPablo Neira Ayuso 588bb69f3bSPablo Neira Ayuso enum nf_flowtable_flags { 598bb69f3bSPablo Neira Ayuso NF_FLOWTABLE_HW_OFFLOAD = 0x1, 608bb69f3bSPablo Neira Ayuso }; 618bb69f3bSPablo Neira Ayuso 623b49e2e9SPablo Neira Ayuso struct nf_flowtable { 6384453a90SFelix Fietkau struct list_head list; 643b49e2e9SPablo Neira Ayuso struct rhashtable rhashtable; 6571a8a63bSPablo Neira Ayuso int priority; 663b49e2e9SPablo Neira Ayuso const struct nf_flowtable_type *type; 673b49e2e9SPablo Neira Ayuso struct delayed_work gc_work; 688bb69f3bSPablo Neira Ayuso unsigned int flags; 698bb69f3bSPablo Neira Ayuso struct flow_block flow_block; 70978703f4SPaul Blakey struct mutex flow_block_lock; /* Guards flow_block */ 718bb69f3bSPablo Neira Ayuso possible_net_t net; 723b49e2e9SPablo Neira Ayuso }; 733b49e2e9SPablo Neira Ayuso 74a5449cdcSPablo Neira Ayuso static inline bool nf_flowtable_hw_offload(struct nf_flowtable *flowtable) 75a5449cdcSPablo Neira Ayuso { 76a5449cdcSPablo Neira Ayuso return flowtable->flags & NF_FLOWTABLE_HW_OFFLOAD; 77a5449cdcSPablo Neira Ayuso } 78a5449cdcSPablo Neira Ayuso 79ac2a6666SPablo Neira Ayuso enum flow_offload_tuple_dir { 80af81f9e7SFelix Fietkau FLOW_OFFLOAD_DIR_ORIGINAL = IP_CT_DIR_ORIGINAL, 81af81f9e7SFelix Fietkau FLOW_OFFLOAD_DIR_REPLY = IP_CT_DIR_REPLY, 82af81f9e7SFelix Fietkau FLOW_OFFLOAD_DIR_MAX = IP_CT_DIR_MAX 83ac2a6666SPablo Neira Ayuso }; 84ac2a6666SPablo Neira Ayuso 85ac2a6666SPablo Neira Ayuso struct flow_offload_tuple { 86ac2a6666SPablo Neira Ayuso union { 87ac2a6666SPablo Neira Ayuso struct in_addr src_v4; 88ac2a6666SPablo Neira Ayuso struct in6_addr src_v6; 89ac2a6666SPablo Neira Ayuso }; 90ac2a6666SPablo Neira Ayuso union { 91ac2a6666SPablo Neira Ayuso struct in_addr dst_v4; 92ac2a6666SPablo Neira Ayuso struct in6_addr dst_v6; 93ac2a6666SPablo Neira Ayuso }; 94ac2a6666SPablo Neira Ayuso struct { 95ac2a6666SPablo Neira Ayuso __be16 src_port; 96ac2a6666SPablo Neira Ayuso __be16 dst_port; 97ac2a6666SPablo Neira Ayuso }; 98ac2a6666SPablo Neira Ayuso 99ac2a6666SPablo Neira Ayuso int iifidx; 100ac2a6666SPablo Neira Ayuso 101ac2a6666SPablo Neira Ayuso u8 l3proto; 102ac2a6666SPablo Neira Ayuso u8 l4proto; 103ac2a6666SPablo Neira Ayuso u8 dir; 104ac2a6666SPablo Neira Ayuso 1054f3780c0SFelix Fietkau u16 mtu; 1064f3780c0SFelix Fietkau 107ac2a6666SPablo Neira Ayuso struct dst_entry *dst_cache; 108ac2a6666SPablo Neira Ayuso }; 109ac2a6666SPablo Neira Ayuso 110ac2a6666SPablo Neira Ayuso struct flow_offload_tuple_rhash { 111ac2a6666SPablo Neira Ayuso struct rhash_head node; 112ac2a6666SPablo Neira Ayuso struct flow_offload_tuple tuple; 113ac2a6666SPablo Neira Ayuso }; 114ac2a6666SPablo Neira Ayuso 115355a8b13SPablo Neira Ayuso enum nf_flow_flags { 116355a8b13SPablo Neira Ayuso NF_FLOW_SNAT, 117355a8b13SPablo Neira Ayuso NF_FLOW_DNAT, 118355a8b13SPablo Neira Ayuso NF_FLOW_TEARDOWN, 119355a8b13SPablo Neira Ayuso NF_FLOW_HW, 120355a8b13SPablo Neira Ayuso NF_FLOW_HW_DYING, 121355a8b13SPablo Neira Ayuso NF_FLOW_HW_DEAD, 122f698fe40SPablo Neira Ayuso NF_FLOW_HW_REFRESH, 123355a8b13SPablo Neira Ayuso }; 124ac2a6666SPablo Neira Ayuso 125f1363e05SPablo Neira Ayuso enum flow_offload_type { 126f1363e05SPablo Neira Ayuso NF_FLOW_OFFLOAD_UNSPEC = 0, 127f1363e05SPablo Neira Ayuso NF_FLOW_OFFLOAD_ROUTE, 128f1363e05SPablo Neira Ayuso }; 129f1363e05SPablo Neira Ayuso 130ac2a6666SPablo Neira Ayuso struct flow_offload { 131ac2a6666SPablo Neira Ayuso struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; 132b32d2f34SPablo Neira Ayuso struct nf_conn *ct; 133355a8b13SPablo Neira Ayuso unsigned long flags; 134f1363e05SPablo Neira Ayuso u16 type; 135ac2a6666SPablo Neira Ayuso u32 timeout; 13662248df8SPablo Neira Ayuso struct rcu_head rcu_head; 137ac2a6666SPablo Neira Ayuso }; 138ac2a6666SPablo Neira Ayuso 139ac2a6666SPablo Neira Ayuso #define NF_FLOW_TIMEOUT (30 * HZ) 140fb46f1b7SPablo Neira Ayuso #define nf_flowtable_time_stamp (u32)jiffies 141fb46f1b7SPablo Neira Ayuso 142fb46f1b7SPablo Neira Ayuso static inline __s32 nf_flow_timeout_delta(unsigned int timeout) 143fb46f1b7SPablo Neira Ayuso { 144fb46f1b7SPablo Neira Ayuso return (__s32)(timeout - nf_flowtable_time_stamp); 145fb46f1b7SPablo Neira Ayuso } 146ac2a6666SPablo Neira Ayuso 147ac2a6666SPablo Neira Ayuso struct nf_flow_route { 148ac2a6666SPablo Neira Ayuso struct { 149ac2a6666SPablo Neira Ayuso struct dst_entry *dst; 150ac2a6666SPablo Neira Ayuso } tuple[FLOW_OFFLOAD_DIR_MAX]; 151ac2a6666SPablo Neira Ayuso }; 152ac2a6666SPablo Neira Ayuso 153f1363e05SPablo Neira Ayuso struct flow_offload *flow_offload_alloc(struct nf_conn *ct); 154ac2a6666SPablo Neira Ayuso void flow_offload_free(struct flow_offload *flow); 155ac2a6666SPablo Neira Ayuso 156978703f4SPaul Blakey int nf_flow_table_offload_add_cb(struct nf_flowtable *flow_table, 157978703f4SPaul Blakey flow_setup_cb_t *cb, void *cb_priv); 158978703f4SPaul Blakey void nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table, 159978703f4SPaul Blakey flow_setup_cb_t *cb, void *cb_priv); 160978703f4SPaul Blakey 161f1363e05SPablo Neira Ayuso int flow_offload_route_init(struct flow_offload *flow, 162f1363e05SPablo Neira Ayuso const struct nf_flow_route *route); 163f1363e05SPablo Neira Ayuso 164ac2a6666SPablo Neira Ayuso int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); 165ac2a6666SPablo Neira Ayuso struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table, 166ac2a6666SPablo Neira Ayuso struct flow_offload_tuple *tuple); 1675f1be84aSTaehee Yoo void nf_flow_table_cleanup(struct net_device *dev); 168c0ea1bcbSPablo Neira Ayuso 169a268de77SFelix Fietkau int nf_flow_table_init(struct nf_flowtable *flow_table); 170b408c5b0SPablo Neira Ayuso void nf_flow_table_free(struct nf_flowtable *flow_table); 171ac2a6666SPablo Neira Ayuso 17259c466ddSFelix Fietkau void flow_offload_teardown(struct flow_offload *flow); 173ac2a6666SPablo Neira Ayuso 174ac2a6666SPablo Neira Ayuso int nf_flow_snat_port(const struct flow_offload *flow, 175ac2a6666SPablo Neira Ayuso struct sk_buff *skb, unsigned int thoff, 176ac2a6666SPablo Neira Ayuso u8 protocol, enum flow_offload_tuple_dir dir); 177ac2a6666SPablo Neira Ayuso int nf_flow_dnat_port(const struct flow_offload *flow, 178ac2a6666SPablo Neira Ayuso struct sk_buff *skb, unsigned int thoff, 179ac2a6666SPablo Neira Ayuso u8 protocol, enum flow_offload_tuple_dir dir); 180ac2a6666SPablo Neira Ayuso 181ac2a6666SPablo Neira Ayuso struct flow_ports { 182ac2a6666SPablo Neira Ayuso __be16 source, dest; 183ac2a6666SPablo Neira Ayuso }; 184ac2a6666SPablo Neira Ayuso 1857c23b629SPablo Neira Ayuso unsigned int nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, 1867c23b629SPablo Neira Ayuso const struct nf_hook_state *state); 1877c23b629SPablo Neira Ayuso unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, 1887c23b629SPablo Neira Ayuso const struct nf_hook_state *state); 1897c23b629SPablo Neira Ayuso 190ac2a6666SPablo Neira Ayuso #define MODULE_ALIAS_NF_FLOWTABLE(family) \ 191ac2a6666SPablo Neira Ayuso MODULE_ALIAS("nf-flowtable-" __stringify(family)) 192ac2a6666SPablo Neira Ayuso 193c29f74e0SPablo Neira Ayuso void nf_flow_offload_add(struct nf_flowtable *flowtable, 194c29f74e0SPablo Neira Ayuso struct flow_offload *flow); 195c29f74e0SPablo Neira Ayuso void nf_flow_offload_del(struct nf_flowtable *flowtable, 196c29f74e0SPablo Neira Ayuso struct flow_offload *flow); 197c29f74e0SPablo Neira Ayuso void nf_flow_offload_stats(struct nf_flowtable *flowtable, 198c29f74e0SPablo Neira Ayuso struct flow_offload *flow); 199c29f74e0SPablo Neira Ayuso 200c29f74e0SPablo Neira Ayuso void nf_flow_table_offload_flush(struct nf_flowtable *flowtable); 201c29f74e0SPablo Neira Ayuso int nf_flow_table_offload_setup(struct nf_flowtable *flowtable, 2028bb69f3bSPablo Neira Ayuso struct net_device *dev, 203c29f74e0SPablo Neira Ayuso enum flow_block_command cmd); 2045c27d8d7SPablo Neira Ayuso int nf_flow_rule_route_ipv4(struct net *net, const struct flow_offload *flow, 2055c27d8d7SPablo Neira Ayuso enum flow_offload_tuple_dir dir, 2065c27d8d7SPablo Neira Ayuso struct nf_flow_rule *flow_rule); 2075c27d8d7SPablo Neira Ayuso int nf_flow_rule_route_ipv6(struct net *net, const struct flow_offload *flow, 208c29f74e0SPablo Neira Ayuso enum flow_offload_tuple_dir dir, 209c29f74e0SPablo Neira Ayuso struct nf_flow_rule *flow_rule); 210c29f74e0SPablo Neira Ayuso 211c29f74e0SPablo Neira Ayuso int nf_flow_table_offload_init(void); 212c29f74e0SPablo Neira Ayuso void nf_flow_table_offload_exit(void); 2138bb69f3bSPablo Neira Ayuso 2140286fbc6SJeremy Sowden #endif /* _NF_FLOW_TABLE_H */ 215