3916 lines · 102.5 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * Copyright (c) 2007-2017 Nicira, Inc. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include "flow.h"#include "datapath.h"#include <linux/uaccess.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/if_ether.h>#include <linux/if_vlan.h>#include <net/llc_pdu.h>#include <linux/kernel.h>#include <linux/jhash.h>#include <linux/jiffies.h>#include <linux/llc.h>#include <linux/module.h>#include <linux/in.h>#include <linux/rcupdate.h>#include <linux/if_arp.h>#include <linux/ip.h>#include <linux/ipv6.h>#include <linux/sctp.h>#include <linux/tcp.h>#include <linux/udp.h>#include <linux/icmp.h>#include <linux/icmpv6.h>#include <linux/rculist.h>#include <net/geneve.h>#include <net/ip.h>#include <net/ipv6.h>#include <net/ndisc.h>#include <net/mpls.h>#include <net/vxlan.h>#include <net/tun_proto.h>#include <net/erspan.h> #include "drop.h"#include "flow_netlink.h" struct ovs_len_tbl {	int len;	const struct ovs_len_tbl *next;}; #define OVS_ATTR_NESTED -1#define OVS_ATTR_VARIABLE -2#define OVS_COPY_ACTIONS_MAX_DEPTH 16 static bool actions_may_change_flow(const struct nlattr *actions){	struct nlattr *nla;	int rem; 	nla_for_each_nested(nla, actions, rem) {		u16 action = nla_type(nla); 		switch (action) {		case OVS_ACTION_ATTR_OUTPUT:		case OVS_ACTION_ATTR_RECIRC:		case OVS_ACTION_ATTR_TRUNC:		case OVS_ACTION_ATTR_USERSPACE:		case OVS_ACTION_ATTR_DROP:		case OVS_ACTION_ATTR_PSAMPLE:			break; 		case OVS_ACTION_ATTR_CT:		case OVS_ACTION_ATTR_CT_CLEAR:		case OVS_ACTION_ATTR_HASH:		case OVS_ACTION_ATTR_POP_ETH:		case OVS_ACTION_ATTR_POP_MPLS:		case OVS_ACTION_ATTR_POP_NSH:		case OVS_ACTION_ATTR_POP_VLAN:		case OVS_ACTION_ATTR_PUSH_ETH:		case OVS_ACTION_ATTR_PUSH_MPLS:		case OVS_ACTION_ATTR_PUSH_NSH:		case OVS_ACTION_ATTR_PUSH_VLAN:		case OVS_ACTION_ATTR_SAMPLE:		case OVS_ACTION_ATTR_SET:		case OVS_ACTION_ATTR_SET_MASKED:		case OVS_ACTION_ATTR_METER:		case OVS_ACTION_ATTR_CHECK_PKT_LEN:		case OVS_ACTION_ATTR_ADD_MPLS:		case OVS_ACTION_ATTR_DEC_TTL:		default:			return true;		}	}	return false;} static void update_range(struct sw_flow_match *match,			 size_t offset, size_t size, bool is_mask){	struct sw_flow_key_range *range;	size_t start = rounddown(offset, sizeof(long));	size_t end = roundup(offset + size, sizeof(long)); 	if (!is_mask)		range = &match->range;	else		range = &match->mask->range; 	if (range->start == range->end) {		range->start = start;		range->end = end;		return;	} 	if (range->start > start)		range->start = start; 	if (range->end < end)		range->end = end;} #define SW_FLOW_KEY_PUT(match, field, value, is_mask) \	do { \		update_range(match, offsetof(struct sw_flow_key, field),    \			     sizeof((match)->key->field), is_mask);	    \		if (is_mask)						    \			(match)->mask->key.field = value;		    \		else							    \			(match)->key->field = value;		            \	} while (0) #define SW_FLOW_KEY_MEMCPY_OFFSET(match, offset, value_p, len, is_mask)	    \	do {								    \		update_range(match, offset, len, is_mask);		    \		if (is_mask)						    \			memcpy((u8 *)&(match)->mask->key + offset, value_p, \			       len);					   \		else							    \			memcpy((u8 *)(match)->key + offset, value_p, len);  \	} while (0) #define SW_FLOW_KEY_MEMCPY(match, field, value_p, len, is_mask)		      \	SW_FLOW_KEY_MEMCPY_OFFSET(match, offsetof(struct sw_flow_key, field), \				  value_p, len, is_mask) #define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask)		    \	do {								    \		update_range(match, offsetof(struct sw_flow_key, field),    \			     sizeof((match)->key->field), is_mask);	    \		if (is_mask)						    \			memset((u8 *)&(match)->mask->key.field, value,      \			       sizeof((match)->mask->key.field));	    \		else							    \			memset((u8 *)&(match)->key->field, value,           \			       sizeof((match)->key->field));                \	} while (0) #define SW_FLOW_KEY_BITMAP_COPY(match, field, value_p, nbits, is_mask) ({     \	update_range(match, offsetof(struct sw_flow_key, field),	      \		     bitmap_size(nbits), is_mask);			      \	bitmap_copy(is_mask ? (match)->mask->key.field : (match)->key->field, \		    value_p, nbits);					      \}) static bool match_validate(const struct sw_flow_match *match,			   u64 key_attrs, u64 mask_attrs, bool log){	u64 key_expected = 0;	u64 mask_allowed = key_attrs;  /* At most allow all key attributes */ 	/* The following mask attributes allowed only if they	 * pass the validation tests. */	mask_allowed &= ~((1 << OVS_KEY_ATTR_IPV4)			| (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4)			| (1 << OVS_KEY_ATTR_IPV6)			| (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6)			| (1 << OVS_KEY_ATTR_TCP)			| (1 << OVS_KEY_ATTR_TCP_FLAGS)			| (1 << OVS_KEY_ATTR_UDP)			| (1 << OVS_KEY_ATTR_SCTP)			| (1 << OVS_KEY_ATTR_ICMP)			| (1 << OVS_KEY_ATTR_ICMPV6)			| (1 << OVS_KEY_ATTR_ARP)			| (1 << OVS_KEY_ATTR_ND)			| (1 << OVS_KEY_ATTR_MPLS)			| (1 << OVS_KEY_ATTR_NSH)); 	/* Always allowed mask fields. */	mask_allowed |= ((1 << OVS_KEY_ATTR_TUNNEL)		       | (1 << OVS_KEY_ATTR_IN_PORT)		       | (1 << OVS_KEY_ATTR_ETHERTYPE)); 	/* Check key attributes. */	if (match->key->eth.type == htons(ETH_P_ARP)			|| match->key->eth.type == htons(ETH_P_RARP)) {		key_expected |= 1 << OVS_KEY_ATTR_ARP;		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))			mask_allowed |= 1 << OVS_KEY_ATTR_ARP;	} 	if (eth_p_mpls(match->key->eth.type)) {		key_expected |= 1 << OVS_KEY_ATTR_MPLS;		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))			mask_allowed |= 1 << OVS_KEY_ATTR_MPLS;	} 	if (match->key->eth.type == htons(ETH_P_IP)) {		key_expected |= 1 << OVS_KEY_ATTR_IPV4;		if (match->mask && match->mask->key.eth.type == htons(0xffff)) {			mask_allowed |= 1 << OVS_KEY_ATTR_IPV4;			mask_allowed |= 1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4;		} 		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {			if (match->key->ip.proto == IPPROTO_UDP) {				key_expected |= 1 << OVS_KEY_ATTR_UDP;				if (match->mask && (match->mask->key.ip.proto == 0xff))					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;			} 			if (match->key->ip.proto == IPPROTO_SCTP) {				key_expected |= 1 << OVS_KEY_ATTR_SCTP;				if (match->mask && (match->mask->key.ip.proto == 0xff))					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;			} 			if (match->key->ip.proto == IPPROTO_TCP) {				key_expected |= 1 << OVS_KEY_ATTR_TCP;				key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS;				if (match->mask && (match->mask->key.ip.proto == 0xff)) {					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;					mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS;				}			} 			if (match->key->ip.proto == IPPROTO_ICMP) {				key_expected |= 1 << OVS_KEY_ATTR_ICMP;				if (match->mask && (match->mask->key.ip.proto == 0xff))					mask_allowed |= 1 << OVS_KEY_ATTR_ICMP;			}		}	} 	if (match->key->eth.type == htons(ETH_P_IPV6)) {		key_expected |= 1 << OVS_KEY_ATTR_IPV6;		if (match->mask && match->mask->key.eth.type == htons(0xffff)) {			mask_allowed |= 1 << OVS_KEY_ATTR_IPV6;			mask_allowed |= 1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6;		} 		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {			if (match->key->ip.proto == IPPROTO_UDP) {				key_expected |= 1 << OVS_KEY_ATTR_UDP;				if (match->mask && (match->mask->key.ip.proto == 0xff))					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;			} 			if (match->key->ip.proto == IPPROTO_SCTP) {				key_expected |= 1 << OVS_KEY_ATTR_SCTP;				if (match->mask && (match->mask->key.ip.proto == 0xff))					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;			} 			if (match->key->ip.proto == IPPROTO_TCP) {				key_expected |= 1 << OVS_KEY_ATTR_TCP;				key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS;				if (match->mask && (match->mask->key.ip.proto == 0xff)) {					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;					mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS;				}			} 			if (match->key->ip.proto == IPPROTO_ICMPV6) {				key_expected |= 1 << OVS_KEY_ATTR_ICMPV6;				if (match->mask && (match->mask->key.ip.proto == 0xff))					mask_allowed |= 1 << OVS_KEY_ATTR_ICMPV6; 				if (match->key->tp.src ==						htons(NDISC_NEIGHBOUR_SOLICITATION) ||				    match->key->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {					key_expected |= 1 << OVS_KEY_ATTR_ND;					/* Original direction conntrack tuple					 * uses the same space as the ND fields					 * in the key, so both are not allowed					 * at the same time.					 */					mask_allowed &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6);					if (match->mask && (match->mask->key.tp.src == htons(0xff)))						mask_allowed |= 1 << OVS_KEY_ATTR_ND;				}			}		}	} 	if (match->key->eth.type == htons(ETH_P_NSH)) {		key_expected |= 1 << OVS_KEY_ATTR_NSH;		if (match->mask &&		    match->mask->key.eth.type == htons(0xffff)) {			mask_allowed |= 1 << OVS_KEY_ATTR_NSH;		}	} 	if ((key_attrs & key_expected) != key_expected) {		/* Key attributes check failed. */		OVS_NLERR(log, "Missing key (keys=%llx, expected=%llx)",			  (unsigned long long)key_attrs,			  (unsigned long long)key_expected);		return false;	} 	if ((mask_attrs & mask_allowed) != mask_attrs) {		/* Mask attributes check failed. */		OVS_NLERR(log, "Unexpected mask (mask=%llx, allowed=%llx)",			  (unsigned long long)mask_attrs,			  (unsigned long long)mask_allowed);		return false;	} 	return true;} size_t ovs_tun_key_attr_size(void){	/* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider	 * updating this function.	 */	return    nla_total_size_64bit(8) /* OVS_TUNNEL_KEY_ATTR_ID */		+ nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_SRC */		+ nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_DST */		+ nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TOS */		+ nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TTL */		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_CSUM */		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_OAM */		+ nla_total_size(256)  /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */		/* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS and		 * OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS is mutually exclusive with		 * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it.		 */		+ nla_total_size(2)    /* OVS_TUNNEL_KEY_ATTR_TP_SRC */		+ nla_total_size(2);   /* OVS_TUNNEL_KEY_ATTR_TP_DST */} static size_t ovs_nsh_key_attr_size(void){	/* Whenever adding new OVS_NSH_KEY_ FIELDS, we should consider	 * updating this function.	 */	return  nla_total_size(NSH_BASE_HDR_LEN) /* OVS_NSH_KEY_ATTR_BASE */		/* OVS_NSH_KEY_ATTR_MD1 and OVS_NSH_KEY_ATTR_MD2 are		 * mutually exclusive, so the bigger one can cover		 * the small one.		 */		+ nla_total_size(NSH_CTX_HDRS_MAX_LEN);} size_t ovs_key_attr_size(void){	/* Whenever adding new OVS_KEY_ FIELDS, we should consider	 * updating this function.	 */	BUILD_BUG_ON(OVS_KEY_ATTR_MAX != 32); 	return    nla_total_size(4)   /* OVS_KEY_ATTR_PRIORITY */		+ nla_total_size(0)   /* OVS_KEY_ATTR_TUNNEL */		  + ovs_tun_key_attr_size()		+ nla_total_size(4)   /* OVS_KEY_ATTR_IN_PORT */		+ nla_total_size(4)   /* OVS_KEY_ATTR_SKB_MARK */		+ nla_total_size(4)   /* OVS_KEY_ATTR_DP_HASH */		+ nla_total_size(4)   /* OVS_KEY_ATTR_RECIRC_ID */		+ nla_total_size(4)   /* OVS_KEY_ATTR_CT_STATE */		+ nla_total_size(2)   /* OVS_KEY_ATTR_CT_ZONE */		+ nla_total_size(4)   /* OVS_KEY_ATTR_CT_MARK */		+ nla_total_size(16)  /* OVS_KEY_ATTR_CT_LABELS */		+ nla_total_size(40)  /* OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6 */		+ nla_total_size(0)   /* OVS_KEY_ATTR_NSH */		  + ovs_nsh_key_attr_size()		+ nla_total_size(12)  /* OVS_KEY_ATTR_ETHERNET */		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */		+ nla_total_size(4)   /* OVS_KEY_ATTR_VLAN */		+ nla_total_size(0)   /* OVS_KEY_ATTR_ENCAP */		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */		+ nla_total_size(40)  /* OVS_KEY_ATTR_IPV6 */		+ nla_total_size(2)   /* OVS_KEY_ATTR_ICMPV6 */		+ nla_total_size(28)  /* OVS_KEY_ATTR_ND */		+ nla_total_size(2);  /* OVS_KEY_ATTR_IPV6_EXTHDRS */} static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] = {	[OVS_VXLAN_EXT_GBP]	    = { .len = sizeof(u32) },}; static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {	[OVS_TUNNEL_KEY_ATTR_ID]	    = { .len = sizeof(u64) },	[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]	    = { .len = sizeof(u32) },	[OVS_TUNNEL_KEY_ATTR_IPV4_DST]	    = { .len = sizeof(u32) },	[OVS_TUNNEL_KEY_ATTR_TOS]	    = { .len = 1 },	[OVS_TUNNEL_KEY_ATTR_TTL]	    = { .len = 1 },	[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = { .len = 0 },	[OVS_TUNNEL_KEY_ATTR_CSUM]	    = { .len = 0 },	[OVS_TUNNEL_KEY_ATTR_TP_SRC]	    = { .len = sizeof(u16) },	[OVS_TUNNEL_KEY_ATTR_TP_DST]	    = { .len = sizeof(u16) },	[OVS_TUNNEL_KEY_ATTR_OAM]	    = { .len = 0 },	[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS]   = { .len = OVS_ATTR_VARIABLE },	[OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS]    = { .len = OVS_ATTR_NESTED,						.next = ovs_vxlan_ext_key_lens },	[OVS_TUNNEL_KEY_ATTR_IPV6_SRC]      = { .len = sizeof(struct in6_addr) },	[OVS_TUNNEL_KEY_ATTR_IPV6_DST]      = { .len = sizeof(struct in6_addr) },	[OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS]   = { .len = OVS_ATTR_VARIABLE },	[OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE]   = { .len = 0 },}; static const struct ovs_len_tblovs_nsh_key_attr_lens[OVS_NSH_KEY_ATTR_MAX + 1] = {	[OVS_NSH_KEY_ATTR_BASE] = { .len = sizeof(struct ovs_nsh_key_base) },	[OVS_NSH_KEY_ATTR_MD1]  = { .len = sizeof(struct ovs_nsh_key_md1) },	[OVS_NSH_KEY_ATTR_MD2]  = { .len = OVS_ATTR_VARIABLE },}; /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute.  */static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {	[OVS_KEY_ATTR_ENCAP]	 = { .len = OVS_ATTR_NESTED },	[OVS_KEY_ATTR_PRIORITY]	 = { .len = sizeof(u32) },	[OVS_KEY_ATTR_IN_PORT]	 = { .len = sizeof(u32) },	[OVS_KEY_ATTR_SKB_MARK]	 = { .len = sizeof(u32) },	[OVS_KEY_ATTR_ETHERNET]	 = { .len = sizeof(struct ovs_key_ethernet) },	[OVS_KEY_ATTR_VLAN]	 = { .len = sizeof(__be16) },	[OVS_KEY_ATTR_ETHERTYPE] = { .len = sizeof(__be16) },	[OVS_KEY_ATTR_IPV4]	 = { .len = sizeof(struct ovs_key_ipv4) },	[OVS_KEY_ATTR_IPV6]	 = { .len = sizeof(struct ovs_key_ipv6) },	[OVS_KEY_ATTR_TCP]	 = { .len = sizeof(struct ovs_key_tcp) },	[OVS_KEY_ATTR_TCP_FLAGS] = { .len = sizeof(__be16) },	[OVS_KEY_ATTR_UDP]	 = { .len = sizeof(struct ovs_key_udp) },	[OVS_KEY_ATTR_SCTP]	 = { .len = sizeof(struct ovs_key_sctp) },	[OVS_KEY_ATTR_ICMP]	 = { .len = sizeof(struct ovs_key_icmp) },	[OVS_KEY_ATTR_ICMPV6]	 = { .len = sizeof(struct ovs_key_icmpv6) },	[OVS_KEY_ATTR_ARP]	 = { .len = sizeof(struct ovs_key_arp) },	[OVS_KEY_ATTR_ND]	 = { .len = sizeof(struct ovs_key_nd) },	[OVS_KEY_ATTR_RECIRC_ID] = { .len = sizeof(u32) },	[OVS_KEY_ATTR_DP_HASH]	 = { .len = sizeof(u32) },	[OVS_KEY_ATTR_TUNNEL]	 = { .len = OVS_ATTR_NESTED,				     .next = ovs_tunnel_key_lens, },	[OVS_KEY_ATTR_MPLS]	 = { .len = OVS_ATTR_VARIABLE },	[OVS_KEY_ATTR_CT_STATE]	 = { .len = sizeof(u32) },	[OVS_KEY_ATTR_CT_ZONE]	 = { .len = sizeof(u16) },	[OVS_KEY_ATTR_CT_MARK]	 = { .len = sizeof(u32) },	[OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },	[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4] = {		.len = sizeof(struct ovs_key_ct_tuple_ipv4) },	[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6] = {		.len = sizeof(struct ovs_key_ct_tuple_ipv6) },	[OVS_KEY_ATTR_NSH]       = { .len = OVS_ATTR_NESTED,				     .next = ovs_nsh_key_attr_lens, },	[OVS_KEY_ATTR_IPV6_EXTHDRS] = {		.len = sizeof(struct ovs_key_ipv6_exthdrs) },}; static bool check_attr_len(unsigned int attr_len, unsigned int expected_len){	return expected_len == attr_len ||	       expected_len == OVS_ATTR_NESTED ||	       expected_len == OVS_ATTR_VARIABLE;} static bool is_all_zero(const u8 *fp, size_t size){	int i; 	if (!fp)		return false; 	for (i = 0; i < size; i++)		if (fp[i])			return false; 	return true;} static int __parse_flow_nlattrs(const struct nlattr *attr,				const struct nlattr *a[],				u64 *attrsp, bool log, bool nz){	const struct nlattr *nla;	u64 attrs;	int rem; 	attrs = *attrsp;	nla_for_each_nested(nla, attr, rem) {		u16 type = nla_type(nla);		int expected_len; 		if (type > OVS_KEY_ATTR_MAX) {			OVS_NLERR(log, "Key type %d is out of range max %d",				  type, OVS_KEY_ATTR_MAX);			return -EINVAL;		} 		if (type == OVS_KEY_ATTR_PACKET_TYPE ||		    type == OVS_KEY_ATTR_ND_EXTENSIONS ||		    type == OVS_KEY_ATTR_TUNNEL_INFO) {			OVS_NLERR(log, "Key type %d is not supported", type);			return -EINVAL;

Lines 1–500 of 3916.