#include <linux/module.h>
#include <linux/openvswitch.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/sctp.h>
#include <linux/static_key.h>
#include <linux/string_helpers.h>
#include <net/ip.h>
#include <net/genetlink.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_count.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_labels.h>
#include <net/netfilter/nf_conntrack_seqadj.h>
#include <net/netfilter/nf_conntrack_timeout.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
#include <net/ipv6_frag.h>
#if IS_ENABLED(CONFIG_NF_NAT)
#include <net/netfilter/nf_nat.h>
#endif
#include <net/netfilter/nf_conntrack_act_ct.h>
#include "datapath.h"
#include "drop.h"
#include "conntrack.h"
#include "flow.h"
#include "flow_netlink.h"
struct ovs_ct_len_tbl { … };
struct md_mark { … };
struct md_labels { … };
enum ovs_ct_nat { … };
struct ovs_conntrack_info { … };
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
#define OVS_CT_LIMIT_UNLIMITED …
#define OVS_CT_LIMIT_DEFAULT …
#define CT_LIMIT_HASH_BUCKETS …
static DEFINE_STATIC_KEY_FALSE(ovs_ct_limit_enabled);
struct ovs_ct_limit { … };
struct ovs_ct_limit_info { … };
static const struct nla_policy ct_limit_policy[OVS_CT_LIMIT_ATTR_MAX + 1] = …;
#endif
static bool labels_nonzero(const struct ovs_key_ct_labels *labels);
static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info);
static u16 key_to_nfproto(const struct sw_flow_key *key)
{ … }
static u8 ovs_ct_get_state(enum ip_conntrack_info ctinfo)
{ … }
static u32 ovs_ct_get_mark(const struct nf_conn *ct)
{ … }
#if NF_CT_LABELS_MAX_SIZE < 16
#error NF_CT_LABELS_MAX_SIZE must be at least 16 bytes
#endif
static void ovs_ct_get_labels(const struct nf_conn *ct,
struct ovs_key_ct_labels *labels)
{ … }
static void __ovs_ct_update_key_orig_tp(struct sw_flow_key *key,
const struct nf_conntrack_tuple *orig,
u8 icmp_proto)
{ … }
static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
const struct nf_conntrack_zone *zone,
const struct nf_conn *ct)
{ … }
static void ovs_ct_update_key(const struct sk_buff *skb,
const struct ovs_conntrack_info *info,
struct sw_flow_key *key, bool post_ct,
bool keep_nat_flags)
{ … }
void ovs_ct_fill_key(const struct sk_buff *skb,
struct sw_flow_key *key,
bool post_ct)
{ … }
int ovs_ct_put_key(const struct sw_flow_key *swkey,
const struct sw_flow_key *output, struct sk_buff *skb)
{ … }
static int ovs_ct_set_mark(struct nf_conn *ct, struct sw_flow_key *key,
u32 ct_mark, u32 mask)
{ … }
static struct nf_conn_labels *ovs_ct_get_conn_labels(struct nf_conn *ct)
{ … }
static int ovs_ct_init_labels(struct nf_conn *ct, struct sw_flow_key *key,
const struct ovs_key_ct_labels *labels,
const struct ovs_key_ct_labels *mask)
{ … }
static int ovs_ct_set_labels(struct nf_conn *ct, struct sw_flow_key *key,
const struct ovs_key_ct_labels *labels,
const struct ovs_key_ct_labels *mask)
{ … }
static int ovs_ct_handle_fragments(struct net *net, struct sw_flow_key *key,
u16 zone, int family, struct sk_buff *skb)
{ … }
static enum ip_conntrack_info
ovs_ct_get_info(const struct nf_conntrack_tuple_hash *h)
{ … }
static struct nf_conn *
ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
u8 l3num, struct sk_buff *skb, bool natted)
{ … }
static
struct nf_conn *ovs_ct_executed(struct net *net,
const struct sw_flow_key *key,
const struct ovs_conntrack_info *info,
struct sk_buff *skb,
bool *ct_executed)
{ … }
static bool skb_nfct_cached(struct net *net,
const struct sw_flow_key *key,
const struct ovs_conntrack_info *info,
struct sk_buff *skb)
{ … }
#if IS_ENABLED(CONFIG_NF_NAT)
static void ovs_nat_update_key(struct sw_flow_key *key,
const struct sk_buff *skb,
enum nf_nat_manip_type maniptype)
{ … }
static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
const struct ovs_conntrack_info *info,
struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
{ … }
#else
static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
const struct ovs_conntrack_info *info,
struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
{
return NF_ACCEPT;
}
#endif
static int verdict_to_errno(unsigned int verdict)
{ … }
static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
const struct ovs_conntrack_info *info,
struct sk_buff *skb)
{ … }
static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
const struct ovs_conntrack_info *info,
struct sk_buff *skb)
{ … }
static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
{ … }
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
static struct hlist_head *ct_limit_hash_bucket(
const struct ovs_ct_limit_info *info, u16 zone)
{ … }
static void ct_limit_set(const struct ovs_ct_limit_info *info,
struct ovs_ct_limit *new_ct_limit)
{ … }
static void ct_limit_del(const struct ovs_ct_limit_info *info, u16 zone)
{ … }
static u32 ct_limit_get(const struct ovs_ct_limit_info *info, u16 zone)
{ … }
static int ovs_ct_check_limit(struct net *net,
const struct ovs_conntrack_info *info,
const struct nf_conntrack_tuple *tuple)
{ … }
#endif
static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
const struct ovs_conntrack_info *info,
struct sk_buff *skb)
{ … }
int ovs_ct_execute(struct net *net, struct sk_buff *skb,
struct sw_flow_key *key,
const struct ovs_conntrack_info *info)
{ … }
int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key)
{ … }
#if IS_ENABLED(CONFIG_NF_NAT)
static int parse_nat(const struct nlattr *attr,
struct ovs_conntrack_info *info, bool log)
{ … }
#endif
static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = …;
static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
const char **helper, bool log)
{ … }
bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
{ … }
int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
const struct sw_flow_key *key,
struct sw_flow_actions **sfa, bool log)
{ … }
#if IS_ENABLED(CONFIG_NF_NAT)
static bool ovs_ct_nat_to_attr(const struct ovs_conntrack_info *info,
struct sk_buff *skb)
{ … }
#endif
int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
struct sk_buff *skb)
{ … }
void ovs_ct_free_action(const struct nlattr *a)
{ … }
static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
{ … }
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
static int ovs_ct_limit_init(struct net *net, struct ovs_net *ovs_net)
{ … }
static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
{ … }
static struct sk_buff *
ovs_ct_limit_cmd_reply_start(struct genl_info *info, u8 cmd,
struct ovs_header **ovs_reply_header)
{ … }
static bool check_zone_id(int zone_id, u16 *pzone)
{ … }
static int ovs_ct_limit_set_zone_limit(struct nlattr *nla_zone_limit,
struct ovs_ct_limit_info *info)
{ … }
static int ovs_ct_limit_del_zone_limit(struct nlattr *nla_zone_limit,
struct ovs_ct_limit_info *info)
{ … }
static int ovs_ct_limit_get_default_limit(struct ovs_ct_limit_info *info,
struct sk_buff *reply)
{ … }
static int __ovs_ct_limit_get_zone_limit(struct net *net,
struct nf_conncount_data *data,
u16 zone_id, u32 limit,
struct sk_buff *reply)
{ … }
static int ovs_ct_limit_get_zone_limit(struct net *net,
struct nlattr *nla_zone_limit,
struct ovs_ct_limit_info *info,
struct sk_buff *reply)
{ … }
static int ovs_ct_limit_get_all_zone_limit(struct net *net,
struct ovs_ct_limit_info *info,
struct sk_buff *reply)
{ … }
static int ovs_ct_limit_cmd_set(struct sk_buff *skb, struct genl_info *info)
{ … }
static int ovs_ct_limit_cmd_del(struct sk_buff *skb, struct genl_info *info)
{ … }
static int ovs_ct_limit_cmd_get(struct sk_buff *skb, struct genl_info *info)
{ … }
static const struct genl_small_ops ct_limit_genl_ops[] = …;
static const struct genl_multicast_group ovs_ct_limit_multicast_group = …;
struct genl_family dp_ct_limit_genl_family __ro_after_init = …;
#endif
int ovs_ct_init(struct net *net)
{ … }
void ovs_ct_exit(struct net *net)
{ … }