diff --git a/SOURCES/0015-ethtool-copy.h-sync-with-net-next.patch b/SOURCES/0015-ethtool-copy.h-sync-with-net-next.patch
new file mode 100644
index 0000000..b8f0db5
--- /dev/null
+++ b/SOURCES/0015-ethtool-copy.h-sync-with-net-next.patch
@@ -0,0 +1,115 @@
+From ac4c40ab13bbd42145331766f74c3928bc9e6d51 Mon Sep 17 00:00:00 2001
+From: Edward Cree <ecree@solarflare.com>
+Date: Fri, 9 Mar 2018 15:03:46 +0000
+Subject: [PATCH 15/18] ethtool-copy.h: sync with net-next
+
+This covers kernel changes up to commit 84a1d9c48200,
+    net: ethtool: extend RXNFC API to support RSS spreading of filter matches
+
+Signed-off-by: Edward Cree <ecree@solarflare.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+(cherry picked from commit 23b2e3b14405221b564c5dd6d7bf48c48e3db2c8)
+---
+ ethtool-copy.h | 32 ++++++++++++++++++++++++++------
+ 1 file changed, 26 insertions(+), 6 deletions(-)
+
+diff --git a/ethtool-copy.h b/ethtool-copy.h
+index f4e7bb2..8cc61e9 100644
+--- a/ethtool-copy.h
++++ b/ethtool-copy.h
+@@ -912,12 +912,15 @@ static __inline__ __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie)
+  * @flow_type: Type of flow to be affected, e.g. %TCP_V4_FLOW
+  * @data: Command-dependent value
+  * @fs: Flow classification rule
++ * @rss_context: RSS context to be affected
+  * @rule_cnt: Number of rules to be affected
+  * @rule_locs: Array of used rule locations
+  *
+  * For %ETHTOOL_GRXFH and %ETHTOOL_SRXFH, @data is a bitmask indicating
+  * the fields included in the flow hash, e.g. %RXH_IP_SRC.  The following
+- * structure fields must not be used.
++ * structure fields must not be used, except that if @flow_type includes
++ * the %FLOW_RSS flag, then @rss_context determines which RSS context to
++ * act on.
+  *
+  * For %ETHTOOL_GRXRINGS, @data is set to the number of RX rings/queues
+  * on return.
+@@ -929,7 +932,9 @@ static __inline__ __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie)
+  * set in @data then special location values should not be used.
+  *
+  * For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the location of an
+- * existing rule on entry and @fs contains the rule on return.
++ * existing rule on entry and @fs contains the rule on return; if
++ * @fs.@flow_type includes the %FLOW_RSS flag, then @rss_context is
++ * filled with the RSS context ID associated with the rule.
+  *
+  * For %ETHTOOL_GRXCLSRLALL, @rule_cnt specifies the array size of the
+  * user buffer for @rule_locs on entry.  On return, @data is the size
+@@ -940,7 +945,11 @@ static __inline__ __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie)
+  * For %ETHTOOL_SRXCLSRLINS, @fs specifies the rule to add or update.
+  * @fs.@location either specifies the location to use or is a special
+  * location value with %RX_CLS_LOC_SPECIAL flag set.  On return,
+- * @fs.@location is the actual rule location.
++ * @fs.@location is the actual rule location.  If @fs.@flow_type
++ * includes the %FLOW_RSS flag, @rss_context is the RSS context ID to
++ * use for flow spreading traffic which matches this rule.  The value
++ * from the rxfh indirection table will be added to @fs.@ring_cookie
++ * to choose which ring to deliver to.
+  *
+  * For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the location of an
+  * existing rule on entry.
+@@ -961,7 +970,10 @@ struct ethtool_rxnfc {
+ 	__u32				flow_type;
+ 	__u64				data;
+ 	struct ethtool_rx_flow_spec	fs;
+-	__u32				rule_cnt;
++	union {
++		__u32			rule_cnt;
++		__u32			rss_context;
++	};
+ 	__u32				rule_locs[0];
+ };
+ 
+@@ -988,7 +1000,11 @@ struct ethtool_rxfh_indir {
+ /**
+  * struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key.
+  * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH
+- * @rss_context: RSS context identifier.
++ * @rss_context: RSS context identifier.  Context 0 is the default for normal
++ *	traffic; other contexts can be referenced as the destination for RX flow
++ *	classification rules.  %ETH_RXFH_CONTEXT_ALLOC is used with command
++ *	%ETHTOOL_SRSSH to allocate a new RSS context; on return this field will
++ *	contain the ID of the newly allocated context.
+  * @indir_size: On entry, the array size of the user buffer for the
+  *	indirection table, which may be zero, or (for %ETHTOOL_SRSSH),
+  *	%ETH_RXFH_INDIR_NO_CHANGE.  On return from %ETHTOOL_GRSSH,
+@@ -1007,7 +1023,8 @@ struct ethtool_rxfh_indir {
+  * size should be returned.  For %ETHTOOL_SRSSH, an @indir_size of
+  * %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested
+  * and a @indir_size of zero means the indir table should be reset to default
+- * values. An hfunc of zero means that hash function setting is not requested.
++ * values (if @rss_context == 0) or that the RSS context should be deleted.
++ * An hfunc of zero means that hash function setting is not requested.
+  */
+ struct ethtool_rxfh {
+ 	__u32   cmd;
+@@ -1019,6 +1036,7 @@ struct ethtool_rxfh {
+ 	__u32	rsvd32;
+ 	__u32   rss_config[0];
+ };
++#define ETH_RXFH_CONTEXT_ALLOC		0xffffffff
+ #define ETH_RXFH_INDIR_NO_CHANGE	0xffffffff
+ 
+ /**
+@@ -1633,6 +1651,8 @@ static __inline__ int ethtool_validate_duplex(__u8 duplex)
+ /* Flag to enable additional fields in struct ethtool_rx_flow_spec */
+ #define	FLOW_EXT	0x80000000
+ #define	FLOW_MAC_EXT	0x40000000
++/* Flag to enable RSS spreading of traffic matching rule (nfc only) */
++#define	FLOW_RSS	0x20000000
+ 
+ /* L3-L4 network traffic flow hash options */
+ #define	RXH_L2DA	(1 << 1)
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0016-ethtool-add-support-for-extra-RSS-contexts-and-RSS-s.patch b/SOURCES/0016-ethtool-add-support-for-extra-RSS-contexts-and-RSS-s.patch
new file mode 100644
index 0000000..1f1ee2a
--- /dev/null
+++ b/SOURCES/0016-ethtool-add-support-for-extra-RSS-contexts-and-RSS-s.patch
@@ -0,0 +1,475 @@
+From 10b4bae4d7f2fa4768fbe90cbfa18ed6059e5a5b Mon Sep 17 00:00:00 2001
+From: Edward Cree <ecree@solarflare.com>
+Date: Fri, 9 Mar 2018 15:04:12 +0000
+Subject: [PATCH 16/18] ethtool: add support for extra RSS contexts and RSS
+ steering filters
+
+RSS contexts can be created on a device with -X ... context new, modified
+ with -X ... context N, and deleted with -X ... context N delete.
+N-tuple filters can be directed at those contexts with -N ... context N.
+
+Signed-off-by: Edward Cree <ecree@solarflare.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+(cherry picked from commit f5d55b967e0c5757e423805a70d1a298e307e91e)
+---
+ ethtool.c  | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
+ internal.h |   4 +-
+ rxclass.c  |  58 +++++++++++++++++++++----
+ 3 files changed, 173 insertions(+), 30 deletions(-)
+
+diff --git a/ethtool.c b/ethtool.c
+index 2e9ee2c..a276fdb 100644
+--- a/ethtool.c
++++ b/ethtool.c
+@@ -1513,7 +1513,7 @@ static void dump_features(const struct feature_defs *defs,
+ 
+ static int dump_rxfhash(int fhash, u64 val)
+ {
+-	switch (fhash) {
++	switch (fhash & ~FLOW_RSS) {
+ 	case TCP_V4_FLOW:
+ 		fprintf(stdout, "TCP over IPV4 flows");
+ 		break;
+@@ -3527,11 +3527,20 @@ static int do_srxclass(struct cmd_context *ctx)
+ 	if (ctx->argc < 2)
+ 		exit_bad_args();
+ 
+-	if (ctx->argc == 3 && !strcmp(ctx->argp[0], "rx-flow-hash")) {
++	if (!strcmp(ctx->argp[0], "rx-flow-hash")) {
+ 		int rx_fhash_set;
+ 		u32 rx_fhash_val;
+ 		struct ethtool_rxnfc nfccmd;
++		bool flow_rss = false;
+ 
++		if (ctx->argc == 5) {
++			if (strcmp(ctx->argp[3], "context"))
++				exit_bad_args();
++			flow_rss = true;
++			nfccmd.rss_context = get_u32(ctx->argp[4], 0);
++		} else if (ctx->argc != 3) {
++			exit_bad_args();
++		}
+ 		rx_fhash_set = rxflow_str_to_type(ctx->argp[1]);
+ 		if (!rx_fhash_set)
+ 			exit_bad_args();
+@@ -3541,16 +3550,19 @@ static int do_srxclass(struct cmd_context *ctx)
+ 		nfccmd.cmd = ETHTOOL_SRXFH;
+ 		nfccmd.flow_type = rx_fhash_set;
+ 		nfccmd.data = rx_fhash_val;
++		if (flow_rss)
++			nfccmd.flow_type |= FLOW_RSS;
+ 
+ 		err = send_ioctl(ctx, &nfccmd);
+ 		if (err < 0)
+ 			perror("Cannot change RX network flow hashing options");
+ 	} else if (!strcmp(ctx->argp[0], "flow-type")) {	
+ 		struct ethtool_rx_flow_spec rx_rule_fs;
++		__u32 rss_context = 0;
+ 
+ 		ctx->argc--;
+ 		ctx->argp++;
+-		if (rxclass_parse_ruleopts(ctx, &rx_rule_fs) < 0)
++		if (rxclass_parse_ruleopts(ctx, &rx_rule_fs, &rss_context) < 0)
+ 			exit_bad_args();
+ 
+ 		/* attempt to add rule via N-tuple specifier */
+@@ -3559,7 +3571,7 @@ static int do_srxclass(struct cmd_context *ctx)
+ 			return 0;
+ 
+ 		/* attempt to add rule via network flow classifier */
+-		err = rxclass_rule_ins(ctx, &rx_rule_fs);
++		err = rxclass_rule_ins(ctx, &rx_rule_fs, rss_context);
+ 		if (err < 0) {
+ 			fprintf(stderr, "Cannot insert"
+ 				" classification rule\n");
+@@ -3588,8 +3600,18 @@ static int do_grxclass(struct cmd_context *ctx)
+ 	struct ethtool_rxnfc nfccmd;
+ 	int err;
+ 
+-	if (ctx->argc == 2 && !strcmp(ctx->argp[0], "rx-flow-hash")) {
++	if (ctx->argc > 0 && !strcmp(ctx->argp[0], "rx-flow-hash")) {
+ 		int rx_fhash_get;
++		bool flow_rss = false;
++
++		if (ctx->argc == 4) {
++			if (strcmp(ctx->argp[2], "context"))
++				exit_bad_args();
++			flow_rss = true;
++			nfccmd.rss_context = get_u32(ctx->argp[3], 0);
++		} else if (ctx->argc != 2) {
++			exit_bad_args();
++		}
+ 
+ 		rx_fhash_get = rxflow_str_to_type(ctx->argp[1]);
+ 		if (!rx_fhash_get)
+@@ -3597,11 +3619,17 @@ static int do_grxclass(struct cmd_context *ctx)
+ 
+ 		nfccmd.cmd = ETHTOOL_GRXFH;
+ 		nfccmd.flow_type = rx_fhash_get;
++		if (flow_rss)
++			nfccmd.flow_type |= FLOW_RSS;
+ 		err = send_ioctl(ctx, &nfccmd);
+-		if (err < 0)
++		if (err < 0) {
+ 			perror("Cannot get RX network flow hashing options");
+-		else
++		} else {
++			if (flow_rss)
++				fprintf(stdout, "For RSS context %u:\n",
++					nfccmd.rss_context);
+ 			dump_rxfhash(rx_fhash_get, nfccmd.data);
++		}
+ 	} else if (ctx->argc == 2 && !strcmp(ctx->argp[0], "rule")) {
+ 		int rx_class_rule_get =
+ 			get_uint_range(ctx->argp[1], 0, INT_MAX);
+@@ -3693,10 +3721,23 @@ static int do_grxfh(struct cmd_context *ctx)
+ 	struct ethtool_rxfh rss_head = {0};
+ 	struct ethtool_rxnfc ring_count;
+ 	struct ethtool_rxfh *rss;
++	u32 rss_context = 0;
+ 	u32 i, indir_bytes;
++	int arg_num = 0;
+ 	char *hkey;
+ 	int err;
+ 
++	while (arg_num < ctx->argc) {
++		if (!strcmp(ctx->argp[arg_num], "context")) {
++			++arg_num;
++			rss_context = get_int_range(ctx->argp[arg_num], 0, 1,
++						    ETH_RXFH_CONTEXT_ALLOC - 1);
++			++arg_num;
++		} else {
++			exit_bad_args();
++		}
++	}
++
+ 	ring_count.cmd = ETHTOOL_GRXRINGS;
+ 	err = send_ioctl(ctx, &ring_count);
+ 	if (err < 0) {
+@@ -3705,6 +3746,7 @@ static int do_grxfh(struct cmd_context *ctx)
+ 	}
+ 
+ 	rss_head.cmd = ETHTOOL_GRSSH;
++	rss_head.rss_context = rss_context;
+ 	err = send_ioctl(ctx, &rss_head);
+ 	if (err < 0 && errno == EOPNOTSUPP) {
+ 		return do_grxfhindir(ctx, &ring_count);
+@@ -3722,6 +3764,7 @@ static int do_grxfh(struct cmd_context *ctx)
+ 	}
+ 
+ 	rss->cmd = ETHTOOL_GRSSH;
++	rss->rss_context = rss_context;
+ 	rss->indir_size = rss_head.indir_size;
+ 	rss->key_size = rss_head.key_size;
+ 	err = send_ioctl(ctx, rss);
+@@ -3882,6 +3925,8 @@ static int do_srxfh(struct cmd_context *ctx)
+ 	u32 req_hfunc = 0;
+ 	u32 entry_size = sizeof(rss_head.rss_config[0]);
+ 	u32 num_weights = 0;
++	u32 rss_context = 0;
++	int delete = 0;
+ 
+ 	if (ctx->argc < 1)
+ 		exit_bad_args();
+@@ -3917,6 +3962,18 @@ static int do_srxfh(struct cmd_context *ctx)
+ 			if (!req_hfunc_name)
+ 				exit_bad_args();
+ 			++arg_num;
++		} else if (!strcmp(ctx->argp[arg_num], "context")) {
++			++arg_num;
++			if(!strcmp(ctx->argp[arg_num], "new"))
++				rss_context = ETH_RXFH_CONTEXT_ALLOC;
++			else
++				rss_context = get_int_range(
++						ctx->argp[arg_num], 0, 1,
++						ETH_RXFH_CONTEXT_ALLOC - 1);
++			++arg_num;
++		} else if (!strcmp(ctx->argp[arg_num], "delete")) {
++			++arg_num;
++			delete = 1;
+ 		} else {
+ 			exit_bad_args();
+ 		}
+@@ -3940,6 +3997,41 @@ static int do_srxfh(struct cmd_context *ctx)
+ 		return 1;
+ 	}
+ 
++	if (rxfhindir_default && rss_context) {
++		fprintf(stderr,
++			"Default and context options are mutually exclusive\n");
++		return 1;
++	}
++
++	if (delete && !rss_context) {
++		fprintf(stderr, "Delete option requires context option\n");
++		return 1;
++	}
++
++	if (delete && rxfhindir_weight) {
++		fprintf(stderr,
++			"Delete and weight options are mutually exclusive\n");
++		return 1;
++	}
++
++	if (delete && rxfhindir_equal) {
++		fprintf(stderr,
++			"Delete and equal options are mutually exclusive\n");
++		return 1;
++	}
++
++	if (delete && rxfhindir_default) {
++		fprintf(stderr,
++			"Delete and default options are mutually exclusive\n");
++		return 1;
++	}
++
++	if (delete && rxfhindir_key) {
++		fprintf(stderr,
++			"Delete and hkey options are mutually exclusive\n");
++		return 1;
++	}
++
+ 	ring_count.cmd = ETHTOOL_GRXRINGS;
+ 	err = send_ioctl(ctx, &ring_count);
+ 	if (err < 0) {
+@@ -3950,7 +4042,7 @@ static int do_srxfh(struct cmd_context *ctx)
+ 	rss_head.cmd = ETHTOOL_GRSSH;
+ 	err = send_ioctl(ctx, &rss_head);
+ 	if (err < 0 && errno == EOPNOTSUPP && !rxfhindir_key &&
+-	    !req_hfunc_name) {
++	    !req_hfunc_name && !rss_context) {
+ 		return do_srxfhindir(ctx, rxfhindir_default, rxfhindir_equal,
+ 				     rxfhindir_weight, num_weights);
+ 	} else if (err < 0) {
+@@ -3998,14 +4090,19 @@ static int do_srxfh(struct cmd_context *ctx)
+ 		goto free;
+ 	}
+ 	rss->cmd = ETHTOOL_SRSSH;
+-	rss->indir_size = rss_head.indir_size;
+-	rss->key_size = rss_head.key_size;
++	rss->rss_context = rss_context;
+ 	rss->hfunc = req_hfunc;
+-
+-	if (fill_indir_table(&rss->indir_size, rss->rss_config, rxfhindir_default,
+-			     rxfhindir_equal, rxfhindir_weight, num_weights)) {
+-		err = 1;
+-		goto free;
++	if (delete) {
++		rss->indir_size = rss->key_size = 0;
++	} else {
++		rss->indir_size = rss_head.indir_size;
++		rss->key_size = rss_head.key_size;
++		if (fill_indir_table(&rss->indir_size, rss->rss_config,
++				     rxfhindir_default, rxfhindir_equal,
++				     rxfhindir_weight, num_weights)) {
++			err = 1;
++			goto free;
++		}
+ 	}
+ 
+ 	if (hkey)
+@@ -4018,6 +4115,8 @@ static int do_srxfh(struct cmd_context *ctx)
+ 	if (err < 0) {
+ 		perror("Cannot set RX flow hash configuration");
+ 		err = 1;
++	} else if (rss_context == ETH_RXFH_CONTEXT_ALLOC) {
++		printf("New RSS context is %d\n", rss->rss_context);
+ 	}
+ 
+ free:
+@@ -4803,12 +4902,12 @@ static const struct option {
+ 	{ "-n|-u|--show-nfc|--show-ntuple", 1, do_grxclass,
+ 	  "Show Rx network flow classification options or rules",
+ 	  "		[ rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|"
+-	  "tcp6|udp6|ah6|esp6|sctp6 |\n"
++	  "tcp6|udp6|ah6|esp6|sctp6 [context %d] |\n"
+ 	  "		  rule %d ]\n" },
+ 	{ "-N|-U|--config-nfc|--config-ntuple", 1, do_srxclass,
+ 	  "Configure Rx network flow classification options or rules",
+ 	  "		rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|"
+-	  "tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r... |\n"
++	  "tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r... [context %d] |\n"
+ 	  "		flow-type ether|ip4|tcp4|udp4|sctp4|ah4|esp4|"
+ 	  "ip6|tcp6|udp6|ah6|esp6|sctp6\n"
+ 	  "			[ src %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n"
+@@ -4827,17 +4926,21 @@ static const struct option {
+ 	  "			[ user-def %x [m %x] ]\n"
+ 	  "			[ dst-mac %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n"
+ 	  "			[ action %d ]\n"
++	  "			[ context %d ]\n"
+ 	  "			[ loc %d]] |\n"
+ 	  "		delete %d\n" },
+ 	{ "-T|--show-time-stamping", 1, do_tsinfo,
+ 	  "Show time stamping capabilities" },
+ 	{ "-x|--show-rxfh-indir|--show-rxfh", 1, do_grxfh,
+-	  "Show Rx flow hash indirection table and/or RSS hash key" },
++	  "Show Rx flow hash indirection table and/or RSS hash key",
++	  "		[ context %d ]\n" },
+ 	{ "-X|--set-rxfh-indir|--rxfh", 1, do_srxfh,
+ 	  "Set Rx flow hash indirection table and/or RSS hash key",
++	  "		[ context %d|new ]\n"
+ 	  "		[ equal N | weight W0 W1 ... | default ]\n"
+ 	  "		[ hkey %x:%x:%x:%x:%x:.... ]\n"
+-	  "		[ hfunc FUNC ]\n" },
++	  "		[ hfunc FUNC ]\n"
++	  "		[ delete ]\n" },
+ 	{ "-f|--flash", 1, do_flash,
+ 	  "Flash firmware image from the specified file to a region on the device",
+ 	  "               FILENAME [ REGION-NUMBER-TO-FLASH ]\n" },
+diff --git a/internal.h b/internal.h
+index 4e658ea..913f4eb 100644
+--- a/internal.h
++++ b/internal.h
+@@ -332,11 +332,11 @@ int vmxnet3_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
+ 
+ /* Rx flow classification */
+ int rxclass_parse_ruleopts(struct cmd_context *ctx,
+-			   struct ethtool_rx_flow_spec *fsp);
++			   struct ethtool_rx_flow_spec *fsp, __u32 *rss_context);
+ int rxclass_rule_getall(struct cmd_context *ctx);
+ int rxclass_rule_get(struct cmd_context *ctx, __u32 loc);
+ int rxclass_rule_ins(struct cmd_context *ctx,
+-		     struct ethtool_rx_flow_spec *fsp);
++		     struct ethtool_rx_flow_spec *fsp, __u32 rss_context);
+ int rxclass_rule_del(struct cmd_context *ctx, __u32 loc);
+ 
+ /* Module EEPROM parsing code */
+diff --git a/rxclass.c b/rxclass.c
+index c7bfeba..39c9eca 100644
+--- a/rxclass.c
++++ b/rxclass.c
+@@ -94,14 +94,15 @@ static void rxclass_print_nfc_spec_ext(struct ethtool_rx_flow_spec *fsp)
+ 	}
+ }
+ 
+-static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp)
++static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp,
++				   __u32 rss_context)
+ {
+ 	unsigned char	*smac, *smacm, *dmac, *dmacm;
+ 	__u32		flow_type;
+ 
+ 	fprintf(stdout,	"Filter: %d\n", fsp->location);
+ 
+-	flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT);
++	flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
+ 
+ 	invert_flow_mask(fsp);
+ 
+@@ -247,6 +248,9 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp)
+ 
+ 	rxclass_print_nfc_spec_ext(fsp);
+ 
++	if (fsp->flow_type & FLOW_RSS)
++		fprintf(stdout, "\tRSS Context ID: %u\n", rss_context);
++
+ 	if (fsp->ring_cookie != RX_CLS_FLOW_DISC)
+ 		fprintf(stdout, "\tAction: Direct to queue %llu\n",
+ 			fsp->ring_cookie);
+@@ -256,10 +260,11 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp)
+ 	fprintf(stdout, "\n");
+ }
+ 
+-static void rxclass_print_rule(struct ethtool_rx_flow_spec *fsp)
++static void rxclass_print_rule(struct ethtool_rx_flow_spec *fsp,
++			       __u32 rss_context)
+ {
+ 	/* print the rule in this location */
+-	switch (fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
++	switch (fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS)) {
+ 	case TCP_V4_FLOW:
+ 	case UDP_V4_FLOW:
+ 	case SCTP_V4_FLOW:
+@@ -272,11 +277,11 @@ static void rxclass_print_rule(struct ethtool_rx_flow_spec *fsp)
+ 	case ESP_V6_FLOW:
+ 	case IPV6_USER_FLOW:
+ 	case ETHER_FLOW:
+-		rxclass_print_nfc_rule(fsp);
++		rxclass_print_nfc_rule(fsp, rss_context);
+ 		break;
+ 	case IPV4_USER_FLOW:
+ 		if (fsp->h_u.usr_ip4_spec.ip_ver == ETH_RX_NFC_IP4)
+-			rxclass_print_nfc_rule(fsp);
++			rxclass_print_nfc_rule(fsp, rss_context);
+ 		else /* IPv6 uses IPV6_USER_FLOW */
+ 			fprintf(stderr, "IPV4_USER_FLOW with wrong ip_ver\n");
+ 		break;
+@@ -320,7 +325,7 @@ int rxclass_rule_get(struct cmd_context *ctx, __u32 loc)
+ 	}
+ 
+ 	/* display rule */
+-	rxclass_print_rule(&nfccmd.fs);
++	rxclass_print_rule(&nfccmd.fs, (__u32)nfccmd.rss_context);
+ 	return err;
+ }
+ 
+@@ -550,7 +555,7 @@ out:
+ }
+ 
+ int rxclass_rule_ins(struct cmd_context *ctx,
+-		     struct ethtool_rx_flow_spec *fsp)
++		     struct ethtool_rx_flow_spec *fsp, __u32 rss_context)
+ {
+ 	struct ethtool_rxnfc nfccmd;
+ 	__u32 loc = fsp->location;
+@@ -568,6 +573,7 @@ int rxclass_rule_ins(struct cmd_context *ctx,
+ 
+ 	/* notify netdev of new rule */
+ 	nfccmd.cmd = ETHTOOL_SRXCLSRLINS;
++	nfccmd.rss_context = rss_context;
+ 	nfccmd.fs = *fsp;
+ 	err = send_ioctl(ctx, &nfccmd);
+ 	if (err < 0)
+@@ -1184,7 +1190,7 @@ static int rxclass_get_mask(char *str, unsigned char *p,
+ }
+ 
+ int rxclass_parse_ruleopts(struct cmd_context *ctx,
+-			   struct ethtool_rx_flow_spec *fsp)
++			   struct ethtool_rx_flow_spec *fsp, __u32 *rss_context)
+ {
+ 	const struct rule_opts *options;
+ 	unsigned char *p = (unsigned char *)fsp;
+@@ -1273,6 +1279,40 @@ int rxclass_parse_ruleopts(struct cmd_context *ctx,
+ 	for (i = 1; i < argc;) {
+ 		const struct rule_opts *opt;
+ 		int idx;
++
++		/* special handling for 'context %d' as it doesn't go in
++		 * the struct ethtool_rx_flow_spec
++		 */
++		if (!strcmp(argp[i], "context")) {
++			unsigned long long val;
++
++			i++;
++			if (i >= argc) {
++				fprintf(stderr, "'context' missing value\n");
++				return -1;
++			}
++
++			if (rxclass_get_ulong(argp[i], &val, 32)) {
++				fprintf(stderr, "Invalid context value[%s]\n",
++					argp[i]);
++				return -1;
++			}
++
++			/* Can't use the ALLOC special value as the context ID
++			 * of a filter to insert
++			 */
++			if ((__u32)val == ETH_RXFH_CONTEXT_ALLOC) {
++				fprintf(stderr, "Bad context value %x\n",
++					(__u32)val);
++				return -1;
++			}
++
++			*rss_context = (__u32)val;
++			fsp->flow_type |= FLOW_RSS;
++			i++;
++			continue;
++		}
++
+ 		for (opt = options, idx = 0; idx < n_opts; idx++, opt++) {
+ 			char mask_name[16];
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0017-ethtool.8-Document-RSS-context-control-and-RSS-filte.patch b/SOURCES/0017-ethtool.8-Document-RSS-context-control-and-RSS-filte.patch
new file mode 100644
index 0000000..1153a9c
--- /dev/null
+++ b/SOURCES/0017-ethtool.8-Document-RSS-context-control-and-RSS-filte.patch
@@ -0,0 +1,75 @@
+From 2fb429c04c2da29701c250351bb8877f9d0e5ac2 Mon Sep 17 00:00:00 2001
+From: Edward Cree <ecree@solarflare.com>
+Date: Fri, 9 Mar 2018 15:04:21 +0000
+Subject: [PATCH 17/18] ethtool.8: Document RSS context control and RSS filters
+
+Signed-off-by: Edward Cree <ecree@solarflare.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+(cherry picked from commit 172d6f10021dcce940d0354b266a9f4bbfde0b94)
+---
+ ethtool.8.in | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/ethtool.8.in b/ethtool.8.in
+index 6816020..dd2e3f5 100644
+--- a/ethtool.8.in
++++ b/ethtool.8.in
+@@ -274,6 +274,7 @@ ethtool \- query or control network driver and hardware settings
+ .BM user\-def
+ .RB [ dst-mac \ \*(MA\ [ m \ \*(MA]]
+ .BN action
++.BN context
+ .BN loc
+ .RB |
+ .br
+@@ -303,6 +304,10 @@ ethtool \- query or control network driver and hardware settings
+ .RB ...\ | \ default \ ]
+ .RB [ hfunc
+ .IR FUNC ]
++.RB [ context
++.I CTX
++.RB |\  new ]
++.RB [ delete ]
+ .HP
+ .B ethtool \-f|\-\-flash
+ .I devname file
+@@ -832,6 +837,13 @@ lB	l.
+ 0 or higher	Rx queue to route the flow
+ .TE
+ .TP
++.BI context \ N
++Specifies the RSS context to spread packets over multiple queues; either
++.B 0
++for the default RSS context, or a value returned by
++.BI ethtool\ -X\  ... \ context
++.BR new .
++.TP
+ .BI loc \ N
+ Specify the location/ID to insert the rule. This will overwrite
+ any rule present in that location and will not go through any
+@@ -883,6 +895,22 @@ must be non-zero and must not exceed the size of the indirection table.
+ .TP
+ .BI default
+ Sets the receive flow hash indirection table to its default value.
++.TP
++\fBcontext \fICTX\fR | \fBnew\fR
++Specifies an RSS context to act on; either
++.B new
++to allocate a new RSS context, or
++.IR CTX ,
++a value returned by a previous
++.IB ... \ context
++.BR new .
++.TP
++.B delete
++Delete the specified RSS context.  May only be used in conjunction with
++.B context
++and a non-zero
++.I CTX
++value.
+ .RE
+ .TP
+ .B \-f \-\-flash
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0018-ethtool-don-t-fall-back-to-grxfhindir-when-context-w.patch b/SOURCES/0018-ethtool-don-t-fall-back-to-grxfhindir-when-context-w.patch
new file mode 100644
index 0000000..9f1cab4
--- /dev/null
+++ b/SOURCES/0018-ethtool-don-t-fall-back-to-grxfhindir-when-context-w.patch
@@ -0,0 +1,34 @@
+From 6ff8142033aed6f9eafe7c4f8a67a55c5a98ab2f Mon Sep 17 00:00:00 2001
+From: Edward Cree <ecree@solarflare.com>
+Date: Mon, 19 Mar 2018 16:52:06 +0000
+Subject: [PATCH 18/18] ethtool: don't fall back to grxfhindir when context was
+ specified
+
+In do_grfxh(), if rss_context is non-zero, we must not fall back to
+ do_grxfhindir() if ETHTOOL_GRSSH fails, for that reads the default RSS
+ context and not the one specified.
+
+Fixes: f5d55b967e0c ("ethtool: add support for extra RSS contexts and RSS steering filters")
+Signed-off-by: Edward Cree <ecree@solarflare.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+(cherry picked from commit 7984d34ea893a529330b6addb959cbf6e3ec026f)
+---
+ ethtool.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ethtool.c b/ethtool.c
+index a276fdb..2ecc13f 100644
+--- a/ethtool.c
++++ b/ethtool.c
+@@ -3748,7 +3748,7 @@ static int do_grxfh(struct cmd_context *ctx)
+ 	rss_head.cmd = ETHTOOL_GRSSH;
+ 	rss_head.rss_context = rss_context;
+ 	err = send_ioctl(ctx, &rss_head);
+-	if (err < 0 && errno == EOPNOTSUPP) {
++	if (err < 0 && errno == EOPNOTSUPP && !rss_context) {
+ 		return do_grxfhindir(ctx, &ring_count);
+ 	} else if (err < 0) {
+ 		perror("Cannot get RX flow hash indir size and/or key size");
+-- 
+1.8.3.1
+
diff --git a/SPECS/ethtool.spec b/SPECS/ethtool.spec
index 03936c1..92b6745 100644
--- a/SPECS/ethtool.spec
+++ b/SPECS/ethtool.spec
@@ -1,13 +1,12 @@
 Name:		ethtool
 Epoch:		2
 Version:	4.8
-Release:	7%{?dist}
+Release:	9%{?dist}
 Summary:	Settings tool for Ethernet NICs
 
 License:	GPLv2
 Group:		Applications/System
-#Old URL:	http://sourceforge.net/projects/gkernel/
-URL:		http://ftp.kernel.org/pub/software/network/%{name}/
+URL:		https://www.kernel.org/pub/software/network/%{name}/
 
 # When using tarball from released upstream version:
 # - http://ftp.kernel.org/pub/software/network/%{name}/%{name}-%{version}.tar.bz2
@@ -35,6 +34,10 @@ Patch10:	0011-ethtool.8-Document-56000-advertise-link-modes.patch
 Patch11:	0012-ethtool-Remove-UDP-Fragmentation-Offload-error-print.patch
 Patch12:	0013-ethtool-copy.h-sync-with-net-next.patch
 Patch13:	0014-ethtool-Support-for-FEC-encoding-control.patch
+Patch14:	0015-ethtool-copy.h-sync-with-net-next.patch
+Patch15:	0016-ethtool-add-support-for-extra-RSS-contexts-and-RSS-s.patch
+Patch16:	0017-ethtool.8-Document-RSS-context-control-and-RSS-filte.patch
+Patch17:	0018-ethtool-don-t-fall-back-to-grxfhindir-when-context-w.patch
 
 %description
 This utility allows querying and changing settings such as speed,
@@ -57,6 +60,10 @@ network devices, especially of Ethernet devices.
 %patch11 -p1
 %patch12 -p1
 %patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
 
 # Only needed when using upstream git
 # aclocal
@@ -79,6 +86,12 @@ make DESTDIR=%{buildroot} INSTALL='install -p' install
 %{_mandir}/man8/%{name}.8*
 
 %changelog
+* Mon Jul  2 2018 Ivan Vecera <ivecera@redhat.com> - 2:4.8-9
+- Added support for extra RSS contexts and steering filters
+
+* Mon Jun 11 2018 Ivan Vecera <ivecera@redhat.com> - 2:4.8-8
+- Fixed RPM URL field in spec file
+
 * Wed Jan 10 2018 Ivan Vecera <ivecera@redhat.com> - 2:4.8-7
 - Fixed synopsis in ethtool man page