Commit 7c460d9b authored by Ben Hutchings's avatar Ben Hutchings

sfc: Extend and abstract efx_filter_spec to cover Huntington/EF10

Replace type field with match_flags.  Add rss_context and match values
covering of most of what is now in the MCDI protocol.

Change some fields into bitfields so that the structure size doesn't grow
beyond 64 bytes.

Ditch the filter decoding functions as it is now easier to pick apart
the abstract structure.

Rewrite ethtool NFC rule functions to set/get filter match flags and
values directly.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent f26e958c
...@@ -799,11 +799,12 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) ...@@ -799,11 +799,12 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
return efx_reset(efx, rc); return efx_reset(efx, rc);
} }
/* MAC address mask including only MC flag */ /* MAC address mask including only I/G bit */
static const u8 mac_addr_mc_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; static const u8 mac_addr_ig_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
#define IP4_ADDR_FULL_MASK ((__force __be32)~0) #define IP4_ADDR_FULL_MASK ((__force __be32)~0)
#define PORT_FULL_MASK ((__force __be16)~0) #define PORT_FULL_MASK ((__force __be16)~0)
#define ETHER_TYPE_FULL_MASK ((__force __be16)~0)
static int efx_ethtool_get_class_rule(struct efx_nic *efx, static int efx_ethtool_get_class_rule(struct efx_nic *efx,
struct ethtool_rx_flow_spec *rule) struct ethtool_rx_flow_spec *rule)
...@@ -813,8 +814,6 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, ...@@ -813,8 +814,6 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
struct ethhdr *mac_entry = &rule->h_u.ether_spec; struct ethhdr *mac_entry = &rule->h_u.ether_spec;
struct ethhdr *mac_mask = &rule->m_u.ether_spec; struct ethhdr *mac_mask = &rule->m_u.ether_spec;
struct efx_filter_spec spec; struct efx_filter_spec spec;
u16 vid;
u8 proto;
int rc; int rc;
rc = efx_filter_get_filter_safe(efx, EFX_FILTER_PRI_MANUAL, rc = efx_filter_get_filter_safe(efx, EFX_FILTER_PRI_MANUAL,
...@@ -827,39 +826,67 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, ...@@ -827,39 +826,67 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
else else
rule->ring_cookie = spec.dmaq_id; rule->ring_cookie = spec.dmaq_id;
if (spec.type == EFX_FILTER_MC_DEF || spec.type == EFX_FILTER_UC_DEF) { if ((spec.match_flags & EFX_FILTER_MATCH_ETHER_TYPE) &&
rule->flow_type = ETHER_FLOW; spec.ether_type == htons(ETH_P_IP) &&
memcpy(mac_mask->h_dest, mac_addr_mc_mask, ETH_ALEN); (spec.match_flags & EFX_FILTER_MATCH_IP_PROTO) &&
if (spec.type == EFX_FILTER_MC_DEF) (spec.ip_proto == IPPROTO_TCP || spec.ip_proto == IPPROTO_UDP) &&
memcpy(mac_entry->h_dest, mac_addr_mc_mask, ETH_ALEN); !(spec.match_flags &
return 0; ~(EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_OUTER_VID |
} EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_REM_HOST |
EFX_FILTER_MATCH_IP_PROTO |
rc = efx_filter_get_eth_local(&spec, &vid, mac_entry->h_dest); EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_REM_PORT))) {
if (rc == 0) { rule->flow_type = ((spec.ip_proto == IPPROTO_TCP) ?
TCP_V4_FLOW : UDP_V4_FLOW);
if (spec.match_flags & EFX_FILTER_MATCH_LOC_HOST) {
ip_entry->ip4dst = spec.loc_host[0];
ip_mask->ip4dst = IP4_ADDR_FULL_MASK;
}
if (spec.match_flags & EFX_FILTER_MATCH_REM_HOST) {
ip_entry->ip4src = spec.rem_host[0];
ip_mask->ip4src = IP4_ADDR_FULL_MASK;
}
if (spec.match_flags & EFX_FILTER_MATCH_LOC_PORT) {
ip_entry->pdst = spec.loc_port;
ip_mask->pdst = PORT_FULL_MASK;
}
if (spec.match_flags & EFX_FILTER_MATCH_REM_PORT) {
ip_entry->psrc = spec.rem_port;
ip_mask->psrc = PORT_FULL_MASK;
}
} else if (!(spec.match_flags &
~(EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_MAC_IG |
EFX_FILTER_MATCH_REM_MAC | EFX_FILTER_MATCH_ETHER_TYPE |
EFX_FILTER_MATCH_OUTER_VID))) {
rule->flow_type = ETHER_FLOW; rule->flow_type = ETHER_FLOW;
memset(mac_mask->h_dest, ~0, ETH_ALEN); if (spec.match_flags &
if (vid != EFX_FILTER_VID_UNSPEC) { (EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_MAC_IG)) {
rule->flow_type |= FLOW_EXT; memcpy(mac_entry->h_dest, spec.loc_mac, ETH_ALEN);
rule->h_ext.vlan_tci = htons(vid); if (spec.match_flags & EFX_FILTER_MATCH_LOC_MAC)
rule->m_ext.vlan_tci = htons(0xfff); memset(mac_mask->h_dest, ~0, ETH_ALEN);
else
memcpy(mac_mask->h_dest, mac_addr_ig_mask,
ETH_ALEN);
} }
return 0; if (spec.match_flags & EFX_FILTER_MATCH_REM_MAC) {
memcpy(mac_entry->h_source, spec.rem_mac, ETH_ALEN);
memset(mac_mask->h_source, ~0, ETH_ALEN);
}
if (spec.match_flags & EFX_FILTER_MATCH_ETHER_TYPE) {
mac_entry->h_proto = spec.ether_type;
mac_mask->h_proto = ETHER_TYPE_FULL_MASK;
}
} else {
/* The above should handle all filters that we insert */
WARN_ON(1);
return -EINVAL;
} }
rc = efx_filter_get_ipv4_local(&spec, &proto, if (spec.match_flags & EFX_FILTER_MATCH_OUTER_VID) {
&ip_entry->ip4dst, &ip_entry->pdst); rule->flow_type |= FLOW_EXT;
if (rc != 0) { rule->h_ext.vlan_tci = spec.outer_vid;
rc = efx_filter_get_ipv4_full( rule->m_ext.vlan_tci = htons(0xfff);
&spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst,
&ip_entry->ip4src, &ip_entry->psrc);
EFX_WARN_ON_PARANOID(rc);
ip_mask->ip4src = IP4_ADDR_FULL_MASK;
ip_mask->psrc = PORT_FULL_MASK;
} }
rule->flow_type = (proto == IPPROTO_TCP) ? TCP_V4_FLOW : UDP_V4_FLOW;
ip_mask->ip4dst = IP4_ADDR_FULL_MASK;
ip_mask->pdst = PORT_FULL_MASK;
return rc; return rc;
} }
...@@ -969,80 +996,78 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx, ...@@ -969,80 +996,78 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
(rule->ring_cookie == RX_CLS_FLOW_DISC) ? (rule->ring_cookie == RX_CLS_FLOW_DISC) ?
EFX_FILTER_RX_DMAQ_ID_DROP : rule->ring_cookie); EFX_FILTER_RX_DMAQ_ID_DROP : rule->ring_cookie);
switch (rule->flow_type) { switch (rule->flow_type & ~FLOW_EXT) {
case TCP_V4_FLOW: case TCP_V4_FLOW:
case UDP_V4_FLOW: { case UDP_V4_FLOW:
u8 proto = (rule->flow_type == TCP_V4_FLOW ? spec.match_flags = (EFX_FILTER_MATCH_ETHER_TYPE |
IPPROTO_TCP : IPPROTO_UDP); EFX_FILTER_MATCH_IP_PROTO);
spec.ether_type = htons(ETH_P_IP);
/* Must match all of destination, */ spec.ip_proto = ((rule->flow_type & ~FLOW_EXT) == TCP_V4_FLOW ?
if (!(ip_mask->ip4dst == IP4_ADDR_FULL_MASK && IPPROTO_TCP : IPPROTO_UDP);
ip_mask->pdst == PORT_FULL_MASK)) if (ip_mask->ip4dst) {
return -EINVAL; if (ip_mask->ip4dst != IP4_ADDR_FULL_MASK)
/* all or none of source, */ return -EINVAL;
if ((ip_mask->ip4src || ip_mask->psrc) && spec.match_flags |= EFX_FILTER_MATCH_LOC_HOST;
!(ip_mask->ip4src == IP4_ADDR_FULL_MASK && spec.loc_host[0] = ip_entry->ip4dst;
ip_mask->psrc == PORT_FULL_MASK)) }
return -EINVAL; if (ip_mask->ip4src) {
/* and nothing else */ if (ip_mask->ip4src != IP4_ADDR_FULL_MASK)
if (ip_mask->tos || rule->m_ext.vlan_tci) return -EINVAL;
spec.match_flags |= EFX_FILTER_MATCH_REM_HOST;
spec.rem_host[0] = ip_entry->ip4src;
}
if (ip_mask->pdst) {
if (ip_mask->pdst != PORT_FULL_MASK)
return -EINVAL;
spec.match_flags |= EFX_FILTER_MATCH_LOC_PORT;
spec.loc_port = ip_entry->pdst;
}
if (ip_mask->psrc) {
if (ip_mask->psrc != PORT_FULL_MASK)
return -EINVAL;
spec.match_flags |= EFX_FILTER_MATCH_REM_PORT;
spec.rem_port = ip_entry->psrc;
}
if (ip_mask->tos)
return -EINVAL; return -EINVAL;
if (ip_mask->ip4src)
rc = efx_filter_set_ipv4_full(&spec, proto,
ip_entry->ip4dst,
ip_entry->pdst,
ip_entry->ip4src,
ip_entry->psrc);
else
rc = efx_filter_set_ipv4_local(&spec, proto,
ip_entry->ip4dst,
ip_entry->pdst);
if (rc)
return rc;
break; break;
}
case ETHER_FLOW | FLOW_EXT:
case ETHER_FLOW: {
u16 vlan_tag_mask = (rule->flow_type & FLOW_EXT ?
ntohs(rule->m_ext.vlan_tci) : 0);
/* Must not match on source address or Ethertype */ case ETHER_FLOW:
if (!is_zero_ether_addr(mac_mask->h_source) || if (!is_zero_ether_addr(mac_mask->h_dest)) {
mac_mask->h_proto) if (ether_addr_equal(mac_mask->h_dest,
return -EINVAL; mac_addr_ig_mask))
spec.match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
/* Is it a default UC or MC filter? */ else if (is_broadcast_ether_addr(mac_mask->h_dest))
if (ether_addr_equal(mac_mask->h_dest, mac_addr_mc_mask) && spec.match_flags |= EFX_FILTER_MATCH_LOC_MAC;
vlan_tag_mask == 0) {
if (is_multicast_ether_addr(mac_entry->h_dest))
rc = efx_filter_set_mc_def(&spec);
else else
rc = efx_filter_set_uc_def(&spec); return -EINVAL;
memcpy(spec.loc_mac, mac_entry->h_dest, ETH_ALEN);
} }
/* Otherwise, it must match all of destination and all if (!is_zero_ether_addr(mac_mask->h_source)) {
* or none of VID. if (!is_broadcast_ether_addr(mac_mask->h_source))
*/ return -EINVAL;
else if (is_broadcast_ether_addr(mac_mask->h_dest) && spec.match_flags |= EFX_FILTER_MATCH_REM_MAC;
(vlan_tag_mask == 0xfff || vlan_tag_mask == 0)) { memcpy(spec.rem_mac, mac_entry->h_source, ETH_ALEN);
rc = efx_filter_set_eth_local( }
&spec, if (mac_mask->h_proto) {
vlan_tag_mask ? if (mac_mask->h_proto != ETHER_TYPE_FULL_MASK)
ntohs(rule->h_ext.vlan_tci) : EFX_FILTER_VID_UNSPEC, return -EINVAL;
mac_entry->h_dest); spec.match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
} else { spec.ether_type = mac_entry->h_proto;
rc = -EINVAL;
} }
if (rc)
return rc;
break; break;
}
default: default:
return -EINVAL; return -EINVAL;
} }
if ((rule->flow_type & FLOW_EXT) && rule->m_ext.vlan_tci) {
if (rule->m_ext.vlan_tci != htons(0xfff))
return -EINVAL;
spec.match_flags |= EFX_FILTER_MATCH_OUTER_VID;
spec.outer_vid = rule->h_ext.vlan_tci;
}
rc = efx_filter_insert_filter(efx, &spec, true); rc = efx_filter_insert_filter(efx, &spec, true);
if (rc < 0) if (rc < 0)
return rc; return rc;
......
This diff is collapsed.
...@@ -11,32 +11,49 @@ ...@@ -11,32 +11,49 @@
#define EFX_FILTER_H #define EFX_FILTER_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/if_ether.h>
#include <asm/byteorder.h>
/** /**
* enum efx_filter_type - type of hardware filter * enum efx_filter_match_flags - Flags for hardware filter match type
* @EFX_FILTER_TCP_FULL: Matching TCP/IPv4 4-tuple * @EFX_FILTER_MATCH_REM_HOST: Match by remote IP host address
* @EFX_FILTER_TCP_WILD: Matching TCP/IPv4 destination (host, port) * @EFX_FILTER_MATCH_LOC_HOST: Match by local IP host address
* @EFX_FILTER_UDP_FULL: Matching UDP/IPv4 4-tuple * @EFX_FILTER_MATCH_REM_MAC: Match by remote MAC address
* @EFX_FILTER_UDP_WILD: Matching UDP/IPv4 destination (host, port) * @EFX_FILTER_MATCH_REM_PORT: Match by remote TCP/UDP port
* @EFX_FILTER_MAC_FULL: Matching Ethernet destination MAC address, VID * @EFX_FILTER_MATCH_LOC_MAC: Match by local MAC address
* @EFX_FILTER_MAC_WILD: Matching Ethernet destination MAC address * @EFX_FILTER_MATCH_LOC_PORT: Match by local TCP/UDP port
* @EFX_FILTER_UC_DEF: Matching all otherwise unmatched unicast * @EFX_FILTER_MATCH_ETHER_TYPE: Match by Ether-type
* @EFX_FILTER_MC_DEF: Matching all otherwise unmatched multicast * @EFX_FILTER_MATCH_INNER_VID: Match by inner VLAN ID
* @EFX_FILTER_UNSPEC: Match type is unspecified * @EFX_FILTER_MATCH_OUTER_VID: Match by outer VLAN ID
* @EFX_FILTER_MATCH_IP_PROTO: Match by IP transport protocol
* @EFX_FILTER_MATCH_LOC_MAC_IG: Match by local MAC address I/G bit.
* Used for RX default unicast and multicast/broadcast filters.
* *
* Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types. * Only some combinations are supported, depending on NIC type:
*
* - Falcon supports RX filters matching by {TCP,UDP}/IPv4 4-tuple or
* local 2-tuple (only implemented for Falcon B0)
*
* - Siena supports RX and TX filters matching by {TCP,UDP}/IPv4 4-tuple
* or local 2-tuple, or local MAC with or without outer VID, and RX
* default filters
*
* - Huntington supports filter matching controlled by firmware, potentially
* using {TCP,UDP}/IPv{4,6} 4-tuple or local 2-tuple, local MAC or I/G bit,
* with or without outer and inner VID
*/ */
enum efx_filter_type { enum efx_filter_match_flags {
EFX_FILTER_TCP_FULL = 0, EFX_FILTER_MATCH_REM_HOST = 0x0001,
EFX_FILTER_TCP_WILD, EFX_FILTER_MATCH_LOC_HOST = 0x0002,
EFX_FILTER_UDP_FULL, EFX_FILTER_MATCH_REM_MAC = 0x0004,
EFX_FILTER_UDP_WILD, EFX_FILTER_MATCH_REM_PORT = 0x0008,
EFX_FILTER_MAC_FULL = 4, EFX_FILTER_MATCH_LOC_MAC = 0x0010,
EFX_FILTER_MAC_WILD, EFX_FILTER_MATCH_LOC_PORT = 0x0020,
EFX_FILTER_UC_DEF = 8, EFX_FILTER_MATCH_ETHER_TYPE = 0x0040,
EFX_FILTER_MC_DEF, EFX_FILTER_MATCH_INNER_VID = 0x0080,
EFX_FILTER_TYPE_COUNT, /* number of specific types */ EFX_FILTER_MATCH_OUTER_VID = 0x0100,
EFX_FILTER_UNSPEC = 0xf, EFX_FILTER_MATCH_IP_PROTO = 0x0200,
EFX_FILTER_MATCH_LOC_MAC_IG = 0x0400,
}; };
/** /**
...@@ -73,29 +90,55 @@ enum efx_filter_flags { ...@@ -73,29 +90,55 @@ enum efx_filter_flags {
/** /**
* struct efx_filter_spec - specification for a hardware filter * struct efx_filter_spec - specification for a hardware filter
* @type: Type of match to be performed, from &enum efx_filter_type * @match_flags: Match type flags, from &enum efx_filter_match_flags
* @priority: Priority of the filter, from &enum efx_filter_priority * @priority: Priority of the filter, from &enum efx_filter_priority
* @flags: Miscellaneous flags, from &enum efx_filter_flags * @flags: Miscellaneous flags, from &enum efx_filter_flags
* @rss_context: RSS context to use, if %EFX_FILTER_FLAG_RX_RSS is set
* @dmaq_id: Source/target queue index, or %EFX_FILTER_RX_DMAQ_ID_DROP for * @dmaq_id: Source/target queue index, or %EFX_FILTER_RX_DMAQ_ID_DROP for
* an RX drop filter * an RX drop filter
* @data: Match data (type-dependent) * @outer_vid: Outer VLAN ID to match, if %EFX_FILTER_MATCH_OUTER_VID is set
* @inner_vid: Inner VLAN ID to match, if %EFX_FILTER_MATCH_INNER_VID is set
* @loc_mac: Local MAC address to match, if %EFX_FILTER_MATCH_LOC_MAC or
* %EFX_FILTER_MATCH_LOC_MAC_IG is set
* @rem_mac: Remote MAC address to match, if %EFX_FILTER_MATCH_REM_MAC is set
* @ether_type: Ether-type to match, if %EFX_FILTER_MATCH_ETHER_TYPE is set
* @ip_proto: IP transport protocol to match, if %EFX_FILTER_MATCH_IP_PROTO
* is set
* @loc_host: Local IP host to match, if %EFX_FILTER_MATCH_LOC_HOST is set
* @rem_host: Remote IP host to match, if %EFX_FILTER_MATCH_REM_HOST is set
* @loc_port: Local TCP/UDP port to match, if %EFX_FILTER_MATCH_LOC_PORT is set
* @rem_port: Remote TCP/UDP port to match, if %EFX_FILTER_MATCH_REM_PORT is set
* *
* Use the efx_filter_set_*() functions to initialise the @type and * The efx_filter_init_rx() or efx_filter_init_tx() function *must* be
* @data fields. * used to initialise the structure. The efx_filter_set_*() functions
* may then be used to set @rss_context, @match_flags and related
* fields.
* *
* The @priority field is used by software to determine whether a new * The @priority field is used by software to determine whether a new
* filter may replace an old one. The hardware priority of a filter * filter may replace an old one. The hardware priority of a filter
* depends on the filter type. * depends on which fields are matched.
*/ */
struct efx_filter_spec { struct efx_filter_spec {
u8 type:4; u32 match_flags:12;
u8 priority:4; u32 priority:2;
u8 flags; u32 flags:6;
u16 dmaq_id; u32 dmaq_id:12;
u32 data[3]; u32 rss_context;
__be16 outer_vid __aligned(4); /* allow jhash2() of match values */
__be16 inner_vid;
u8 loc_mac[ETH_ALEN];
u8 rem_mac[ETH_ALEN];
__be16 ether_type;
u8 ip_proto;
__be32 loc_host[4];
__be32 rem_host[4];
__be16 loc_port;
__be16 rem_port;
/* total 64 bytes */
}; };
enum { enum {
EFX_FILTER_RSS_CONTEXT_DEFAULT = 0xffffffff,
EFX_FILTER_RX_DMAQ_ID_DROP = 0xfff EFX_FILTER_RX_DMAQ_ID_DROP = 0xfff
}; };
...@@ -104,39 +147,116 @@ static inline void efx_filter_init_rx(struct efx_filter_spec *spec, ...@@ -104,39 +147,116 @@ static inline void efx_filter_init_rx(struct efx_filter_spec *spec,
enum efx_filter_flags flags, enum efx_filter_flags flags,
unsigned rxq_id) unsigned rxq_id)
{ {
spec->type = EFX_FILTER_UNSPEC; memset(spec, 0, sizeof(*spec));
spec->priority = priority; spec->priority = priority;
spec->flags = EFX_FILTER_FLAG_RX | flags; spec->flags = EFX_FILTER_FLAG_RX | flags;
spec->rss_context = EFX_FILTER_RSS_CONTEXT_DEFAULT;
spec->dmaq_id = rxq_id; spec->dmaq_id = rxq_id;
} }
static inline void efx_filter_init_tx(struct efx_filter_spec *spec, static inline void efx_filter_init_tx(struct efx_filter_spec *spec,
unsigned txq_id) unsigned txq_id)
{ {
spec->type = EFX_FILTER_UNSPEC; memset(spec, 0, sizeof(*spec));
spec->priority = EFX_FILTER_PRI_REQUIRED; spec->priority = EFX_FILTER_PRI_REQUIRED;
spec->flags = EFX_FILTER_FLAG_TX; spec->flags = EFX_FILTER_FLAG_TX;
spec->dmaq_id = txq_id; spec->dmaq_id = txq_id;
} }
extern int efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto, /**
__be32 host, __be16 port); * efx_filter_set_ipv4_local - specify IPv4 host, transport protocol and port
extern int efx_filter_get_ipv4_local(const struct efx_filter_spec *spec, * @spec: Specification to initialise
u8 *proto, __be32 *host, __be16 *port); * @proto: Transport layer protocol number
extern int efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto, * @host: Local host address (network byte order)
__be32 host, __be16 port, * @port: Local port (network byte order)
__be32 rhost, __be16 rport); */
extern int efx_filter_get_ipv4_full(const struct efx_filter_spec *spec, static inline int
u8 *proto, __be32 *host, __be16 *port, efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto,
__be32 *rhost, __be16 *rport); __be32 host, __be16 port)
extern int efx_filter_set_eth_local(struct efx_filter_spec *spec, {
u16 vid, const u8 *addr); spec->match_flags |=
extern int efx_filter_get_eth_local(const struct efx_filter_spec *spec, EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
u16 *vid, u8 *addr); EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
extern int efx_filter_set_uc_def(struct efx_filter_spec *spec); spec->ether_type = htons(ETH_P_IP);
extern int efx_filter_set_mc_def(struct efx_filter_spec *spec); spec->ip_proto = proto;
spec->loc_host[0] = host;
spec->loc_port = port;
return 0;
}
/**
* efx_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports
* @spec: Specification to initialise
* @proto: Transport layer protocol number
* @lhost: Local host address (network byte order)
* @lport: Local port (network byte order)
* @rhost: Remote host address (network byte order)
* @rport: Remote port (network byte order)
*/
static inline int
efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto,
__be32 lhost, __be16 lport,
__be32 rhost, __be16 rport)
{
spec->match_flags |=
EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
spec->ether_type = htons(ETH_P_IP);
spec->ip_proto = proto;
spec->loc_host[0] = lhost;
spec->loc_port = lport;
spec->rem_host[0] = rhost;
spec->rem_port = rport;
return 0;
}
enum { enum {
EFX_FILTER_VID_UNSPEC = 0xffff, EFX_FILTER_VID_UNSPEC = 0xffff,
}; };
/**
* efx_filter_set_eth_local - specify local Ethernet address and/or VID
* @spec: Specification to initialise
* @vid: Outer VLAN ID to match, or %EFX_FILTER_VID_UNSPEC
* @addr: Local Ethernet MAC address, or %NULL
*/
static inline int efx_filter_set_eth_local(struct efx_filter_spec *spec,
u16 vid, const u8 *addr)
{
if (vid == EFX_FILTER_VID_UNSPEC && addr == NULL)
return -EINVAL;
if (vid != EFX_FILTER_VID_UNSPEC) {
spec->match_flags |= EFX_FILTER_MATCH_OUTER_VID;
spec->outer_vid = htons(vid);
}
if (addr != NULL) {
spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC;
memcpy(spec->loc_mac, addr, ETH_ALEN);
}
return 0;
}
/**
* efx_filter_set_uc_def - specify matching otherwise-unmatched unicast
* @spec: Specification to initialise
*/
static inline int efx_filter_set_uc_def(struct efx_filter_spec *spec)
{
spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
return 0;
}
/**
* efx_filter_set_mc_def - specify matching otherwise-unmatched multicast
* @spec: Specification to initialise
*/
static inline int efx_filter_set_mc_def(struct efx_filter_spec *spec)
{
spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
spec->loc_mac[0] = 1;
return 0;
}
#endif /* EFX_FILTER_H */ #endif /* EFX_FILTER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment