* Re: [net PATCH 1/2] net: Disable segmentation if checksumming is not supported
From: Alexander Duyck @ 2016-05-02 16:48 UTC (permalink / raw)
To: Tom Herbert
Cc: Alexander Duyck, Linux Kernel Network Developers, Or Gerlitz,
David S. Miller
In-Reply-To: <CALx6S36=dHesn65aWWiiC=rRjmOW3mZa3ymk0oq5JBncg6SEnA@mail.gmail.com>
On Mon, May 2, 2016 at 9:33 AM, Tom Herbert <tom@herbertland.com> wrote:
> On Mon, May 2, 2016 at 9:25 AM, Alexander Duyck <aduyck@mirantis.com> wrote:
>> In the case of the mlx4 and mlx5 driver they do not support IPv6 checksum
>> offload for tunnels. With this being the case we should disable GSO in
>> addition to the checksum offload features when we find that a device cannot
>> perform a checksum on a given packet type.
>>
> I'm not sure I understand this. If device can't support checksum
> offload for tunnels doesn't that mean we have to do the checksum on
> host regardless of whether GSO is being done?
The use of the term GSO here might be the confusing part. Basically
the issue is the hardware advertises it can do TSO for IPv4 on
encapsulated frames, however it doesn't indicate it can do IPv6
checksum offload. So what ends up happening is that in the case of a
v4 over v6 tunnel we were going through validate_xmit_skb which will
check things in netif_skb_features and come out supporting the TSO but
no checksums. As a result we would fall through and hit
skb_checksum_help and trigger the warn on in there because we had TSO
requested even though we couldn't do the checksum.
Basically I am just extending the kind of logic we have in
netdev_fix_features so that if we cannot support checksumming the
frame then we cannot support segmenting it.
- Alex
^ permalink raw reply
* Re: [PATCHv4] netem: Segment GSO packets on enqueue
From: Eric Dumazet @ 2016-05-02 16:56 UTC (permalink / raw)
To: Neil Horman; +Cc: netdev, Jamal Hadi Salim, David S. Miller, netem, stephen
In-Reply-To: <1462206015-3484-1-git-send-email-nhorman@tuxdriver.com>
On Mon, 2016-05-02 at 12:20 -0400, Neil Horman wrote:
> This was recently reported to me, and reproduced on the latest net kernel,
> when attempting to run netperf from a host that had a netem qdisc attached
> to the egress interface:
Acked-by: Eric Dumazet <edumazet@google.com>
Thanks Neil.
^ permalink raw reply
* [ethtool PATCH v7 0/2] add support for new ETHTOOL_xLINKSETTINGS ioctls
From: David Decotigny @ 2016-05-02 17:00 UTC (permalink / raw)
To: netdev
Cc: Jeff Garzik, Ben Hutchings, David Miller, Vidya Sagar Ravipati,
Joe Perches, David Decotigny
From: David Decotigny <decot@googlers.com>
[ this is a plain re-post, same v7 as the ones previously sent ]
History:
v7
added ref to related kernel commit in netlink ioctl patch description
v6
re-added last patch, to use AF_NETLINK when AF_INET not available
v5
rebased main patch, removed last patch "use AF_LOCAL when AF_INET
not available"
v4
review Ben Hutchings:
using AF_UNIX instead of INET6 in the absence of v4 sockets
use stdbool.h
do_seeprom always fails when offset/length out of bounds
sync to latest ethtool.h + kernel.h from net-next
__SANE_USERSPACE_TYPES__ always defined
cosmetic updates for var == const tests
cosmetic updates for associativity in tests
v3
TRUE/FALSE obvious-ification
v2
added do_seeprom patch
added netdev <at> as recipient
v1
initial submission
############################################
# Patch Set Summary:
David Decotigny (2):
ethtool.c: add support for ETHTOOL_xLINKSETTINGS ioctls
ethtool: use netlink socket when AF_INET not available
configure.ac | 2 +-
ethtool.c | 688 ++++++++++++++++++++++++++++++++++++++++++++-------------
internal.h | 67 ++++++
test-cmdline.c | 13 ++
4 files changed, 611 insertions(+), 159 deletions(-)
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply
* [ethtool PATCH v7 1/2] ethtool.c: add support for ETHTOOL_xLINKSETTINGS ioctls
From: David Decotigny @ 2016-05-02 17:00 UTC (permalink / raw)
To: netdev
Cc: Jeff Garzik, Ben Hutchings, David Miller, Vidya Sagar Ravipati,
Joe Perches, David Decotigny
In-Reply-To: <1462208411-114371-1-git-send-email-ddecotig@gmail.com>
From: David Decotigny <decot@googlers.com>
More info with kernel commit 8d3f2806f8fb ("Merge branch
'ethtool-ksettings'").
Note: The new features implemented in this patch depend on kernel
commit 793cf87de9d1 ("Set cmd field in ETHTOOL_GLINKSETTINGS response to
wrong nwords").
Signed-off-by: David Decotigny <decot@googlers.com>
---
ethtool.c | 681 ++++++++++++++++++++++++++++++++++++++++++++-------------
internal.h | 67 ++++++
test-cmdline.c | 13 ++
3 files changed, 603 insertions(+), 158 deletions(-)
diff --git a/ethtool.c b/ethtool.c
index 0cd0d4f..cb3d971 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -47,42 +47,6 @@
#define MAX_ADDR_LEN 32
#endif
-#define ALL_ADVERTISED_MODES \
- (ADVERTISED_10baseT_Half | \
- ADVERTISED_10baseT_Full | \
- ADVERTISED_100baseT_Half | \
- ADVERTISED_100baseT_Full | \
- ADVERTISED_1000baseT_Half | \
- ADVERTISED_1000baseT_Full | \
- ADVERTISED_1000baseKX_Full| \
- ADVERTISED_2500baseX_Full | \
- ADVERTISED_10000baseT_Full | \
- ADVERTISED_10000baseKX4_Full | \
- ADVERTISED_10000baseKR_Full | \
- ADVERTISED_10000baseR_FEC | \
- ADVERTISED_20000baseMLD2_Full | \
- ADVERTISED_20000baseKR2_Full | \
- ADVERTISED_40000baseKR4_Full | \
- ADVERTISED_40000baseCR4_Full | \
- ADVERTISED_40000baseSR4_Full | \
- ADVERTISED_40000baseLR4_Full | \
- ADVERTISED_56000baseKR4_Full | \
- ADVERTISED_56000baseCR4_Full | \
- ADVERTISED_56000baseSR4_Full | \
- ADVERTISED_56000baseLR4_Full)
-
-#define ALL_ADVERTISED_FLAGS \
- (ADVERTISED_Autoneg | \
- ADVERTISED_TP | \
- ADVERTISED_AUI | \
- ADVERTISED_MII | \
- ADVERTISED_FIBRE | \
- ADVERTISED_BNC | \
- ADVERTISED_Pause | \
- ADVERTISED_Asym_Pause | \
- ADVERTISED_Backplane | \
- ALL_ADVERTISED_MODES)
-
#ifndef HAVE_NETIF_MSG
enum {
NETIF_MSG_DRV = 0x0001,
@@ -293,6 +257,43 @@ static void get_mac_addr(char *src, unsigned char *dest)
}
}
+static int parse_hex_u32_bitmap(const char *s,
+ unsigned int nbits, u32 *result)
+{
+ const unsigned int nwords = __KERNEL_DIV_ROUND_UP(nbits, 32);
+ size_t slen = strlen(s);
+ size_t i;
+
+ /* ignore optional '0x' prefix */
+ if ((slen > 2) && (strncasecmp(s, "0x", 2) == 0)) {
+ slen -= 2;
+ s += 2;
+ }
+
+ if (slen > 8 * nwords) /* up to 2 digits per byte */
+ return -1;
+
+ memset(result, 0, 4 * nwords);
+ for (i = 0 ; i < slen ; ++i) {
+ const unsigned int shift = (slen - 1 - i) * 4;
+ u32 *dest = &result[shift / 32];
+ u32 nibble;
+
+ if ('a' <= s[i] && s[i] <= 'f')
+ nibble = 0xa + (s[i] - 'a');
+ else if ('A' <= s[i] && s[i] <= 'F')
+ nibble = 0xa + (s[i] - 'A');
+ else if ('0' <= s[i] && s[i] <= '9')
+ nibble = (s[i] - '0');
+ else
+ return -1;
+
+ *dest |= (nibble << (shift % 32));
+ }
+
+ return 0;
+}
+
static void parse_generic_cmdline(struct cmd_context *ctx,
int *changed,
struct cmdline_info *info,
@@ -472,64 +473,157 @@ static int do_version(struct cmd_context *ctx)
return 0;
}
-static void dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
- int link_mode_only);
+/* link mode routines */
-static void dump_supported(struct ethtool_cmd *ep)
+static __ETHTOOL_DECLARE_LINK_MODE_MASK(all_advertised_modes);
+static __ETHTOOL_DECLARE_LINK_MODE_MASK(all_advertised_flags);
+
+static void init_global_link_mode_masks(void)
{
- u32 mask = ep->supported;
+ static const enum ethtool_link_mode_bit_indices
+ all_advertised_modes_bits[] = {
+ ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+ ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+ ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+ ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+ ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+ ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT,
+ ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
+ ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
+ ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
+ ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
+ ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
+ };
+ static const enum ethtool_link_mode_bit_indices
+ additional_advertised_flags_bits[] = {
+ ETHTOOL_LINK_MODE_Autoneg_BIT,
+ ETHTOOL_LINK_MODE_TP_BIT,
+ ETHTOOL_LINK_MODE_AUI_BIT,
+ ETHTOOL_LINK_MODE_MII_BIT,
+ ETHTOOL_LINK_MODE_FIBRE_BIT,
+ ETHTOOL_LINK_MODE_BNC_BIT,
+ ETHTOOL_LINK_MODE_Pause_BIT,
+ ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+ ETHTOOL_LINK_MODE_Backplane_BIT,
+ };
+ unsigned int i;
+ ethtool_link_mode_zero(all_advertised_modes);
+ ethtool_link_mode_zero(all_advertised_flags);
+ for (i = 0 ; i < ARRAY_SIZE(all_advertised_modes_bits) ; ++i) {
+ ethtool_link_mode_set_bit(all_advertised_modes_bits[i],
+ all_advertised_modes);
+ ethtool_link_mode_set_bit(all_advertised_modes_bits[i],
+ all_advertised_flags);
+ }
+
+ for (i = 0 ; i < ARRAY_SIZE(additional_advertised_flags_bits) ; ++i) {
+ ethtool_link_mode_set_bit(
+ additional_advertised_flags_bits[i],
+ all_advertised_flags);
+ }
+}
+
+static void dump_link_caps(const char *prefix, const char *an_prefix,
+ const u32 *mask, int link_mode_only);
+
+static void dump_supported(const struct ethtool_link_usettings *link_usettings)
+{
fprintf(stdout, " Supported ports: [ ");
- if (mask & SUPPORTED_TP)
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_TP_BIT,
+ link_usettings->link_modes.supported))
fprintf(stdout, "TP ");
- if (mask & SUPPORTED_AUI)
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_AUI_BIT,
+ link_usettings->link_modes.supported))
fprintf(stdout, "AUI ");
- if (mask & SUPPORTED_BNC)
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_BNC_BIT,
+ link_usettings->link_modes.supported))
fprintf(stdout, "BNC ");
- if (mask & SUPPORTED_MII)
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_MII_BIT,
+ link_usettings->link_modes.supported))
fprintf(stdout, "MII ");
- if (mask & SUPPORTED_FIBRE)
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_FIBRE_BIT,
+ link_usettings->link_modes.supported))
fprintf(stdout, "FIBRE ");
- if (mask & SUPPORTED_Backplane)
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_Backplane_BIT,
+ link_usettings->link_modes.supported))
fprintf(stdout, "Backplane ");
fprintf(stdout, "]\n");
- dump_link_caps("Supported", "Supports", mask, 0);
+ dump_link_caps("Supported", "Supports",
+ link_usettings->link_modes.supported, 0);
}
/* Print link capability flags (supported, advertised or lp_advertised).
* Assumes that the corresponding SUPPORTED and ADVERTISED flags are equal.
*/
-static void
-dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
- int link_mode_only)
+static void dump_link_caps(const char *prefix, const char *an_prefix,
+ const u32 *mask, int link_mode_only)
{
static const struct {
int same_line; /* print on same line as previous */
- u32 value;
+ unsigned int bit_index;
const char *name;
} mode_defs[] = {
- { 0, ADVERTISED_10baseT_Half, "10baseT/Half" },
- { 1, ADVERTISED_10baseT_Full, "10baseT/Full" },
- { 0, ADVERTISED_100baseT_Half, "100baseT/Half" },
- { 1, ADVERTISED_100baseT_Full, "100baseT/Full" },
- { 0, ADVERTISED_1000baseT_Half, "1000baseT/Half" },
- { 1, ADVERTISED_1000baseT_Full, "1000baseT/Full" },
- { 0, ADVERTISED_1000baseKX_Full, "1000baseKX/Full" },
- { 0, ADVERTISED_2500baseX_Full, "2500baseX/Full" },
- { 0, ADVERTISED_10000baseT_Full, "10000baseT/Full" },
- { 0, ADVERTISED_10000baseKX4_Full, "10000baseKX4/Full" },
- { 0, ADVERTISED_10000baseKR_Full, "10000baseKR/Full" },
- { 0, ADVERTISED_20000baseMLD2_Full, "20000baseMLD2/Full" },
- { 0, ADVERTISED_20000baseKR2_Full, "20000baseKR2/Full" },
- { 0, ADVERTISED_40000baseKR4_Full, "40000baseKR4/Full" },
- { 0, ADVERTISED_40000baseCR4_Full, "40000baseCR4/Full" },
- { 0, ADVERTISED_40000baseSR4_Full, "40000baseSR4/Full" },
- { 0, ADVERTISED_40000baseLR4_Full, "40000baseLR4/Full" },
- { 0, ADVERTISED_56000baseKR4_Full, "56000baseKR4/Full" },
- { 0, ADVERTISED_56000baseCR4_Full, "56000baseCR4/Full" },
- { 0, ADVERTISED_56000baseSR4_Full, "56000baseSR4/Full" },
- { 0, ADVERTISED_56000baseLR4_Full, "56000baseLR4/Full" },
+ { 0, ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+ "10baseT/Half" },
+ { 1, ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+ "10baseT/Full" },
+ { 0, ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+ "100baseT/Half" },
+ { 1, ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ "100baseT/Full" },
+ { 0, ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+ "1000baseT/Half" },
+ { 1, ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ "1000baseT/Full" },
+ { 0, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+ "1000baseKX/Full" },
+ { 0, ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
+ "2500baseX/Full" },
+ { 0, ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+ "10000baseT/Full" },
+ { 0, ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+ "10000baseKX4/Full" },
+ { 0, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+ "10000baseKR/Full" },
+ { 0, ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT,
+ "20000baseMLD2/Full" },
+ { 0, ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
+ "20000baseKR2/Full" },
+ { 0, ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
+ "40000baseKR4/Full" },
+ { 0, ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
+ "40000baseCR4/Full" },
+ { 0, ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
+ "40000baseSR4/Full" },
+ { 0, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
+ "40000baseLR4/Full" },
+ { 0, ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
+ "56000baseKR4/Full" },
+ { 0, ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
+ "56000baseCR4/Full" },
+ { 0, ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
+ "56000baseSR4/Full" },
+ { 0, ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
+ "56000baseLR4/Full" },
};
int indent;
int did1, new_line_pend, i;
@@ -546,7 +640,8 @@ dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
for (i = 0; i < ARRAY_SIZE(mode_defs); i++) {
if (did1 && !mode_defs[i].same_line)
new_line_pend = 1;
- if (mask & mode_defs[i].value) {
+ if (ethtool_link_mode_test_bit(mode_defs[i].bit_index,
+ mask)) {
if (new_line_pend) {
fprintf(stdout, "\n");
fprintf(stdout, " %*s", indent, "");
@@ -562,46 +657,52 @@ dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
if (!link_mode_only) {
fprintf(stdout, " %s pause frame use: ", prefix);
- if (mask & ADVERTISED_Pause) {
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_Pause_BIT, mask)) {
fprintf(stdout, "Symmetric");
- if (mask & ADVERTISED_Asym_Pause)
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask))
fprintf(stdout, " Receive-only");
fprintf(stdout, "\n");
} else {
- if (mask & ADVERTISED_Asym_Pause)
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask))
fprintf(stdout, "Transmit-only\n");
else
fprintf(stdout, "No\n");
}
fprintf(stdout, " %s auto-negotiation: ", an_prefix);
- if (mask & ADVERTISED_Autoneg)
+ if (ethtool_link_mode_test_bit(
+ ETHTOOL_LINK_MODE_Autoneg_BIT, mask))
fprintf(stdout, "Yes\n");
else
fprintf(stdout, "No\n");
}
}
-static int dump_ecmd(struct ethtool_cmd *ep)
+static int
+dump_link_usettings(const struct ethtool_link_usettings *link_usettings)
{
- u32 speed;
-
- dump_supported(ep);
- dump_link_caps("Advertised", "Advertised", ep->advertising, 0);
- if (ep->lp_advertising)
+ dump_supported(link_usettings);
+ dump_link_caps("Advertised", "Advertised",
+ link_usettings->link_modes.advertising, 0);
+ if (!ethtool_link_mode_is_empty(
+ link_usettings->link_modes.lp_advertising))
dump_link_caps("Link partner advertised",
- "Link partner advertised", ep->lp_advertising,
- 0);
+ "Link partner advertised",
+ link_usettings->link_modes.lp_advertising, 0);
fprintf(stdout, " Speed: ");
- speed = ethtool_cmd_speed(ep);
- if (speed == 0 || speed == (u16)(-1) || speed == (u32)(-1))
+ if (link_usettings->base.speed == 0
+ || link_usettings->base.speed == (u16)(-1)
+ || link_usettings->base.speed == (u32)(-1))
fprintf(stdout, "Unknown!\n");
else
- fprintf(stdout, "%uMb/s\n", speed);
+ fprintf(stdout, "%uMb/s\n", link_usettings->base.speed);
fprintf(stdout, " Duplex: ");
- switch (ep->duplex) {
+ switch (link_usettings->base.duplex) {
case DUPLEX_HALF:
fprintf(stdout, "Half\n");
break;
@@ -609,12 +710,12 @@ static int dump_ecmd(struct ethtool_cmd *ep)
fprintf(stdout, "Full\n");
break;
default:
- fprintf(stdout, "Unknown! (%i)\n", ep->duplex);
+ fprintf(stdout, "Unknown! (%i)\n", link_usettings->base.duplex);
break;
};
fprintf(stdout, " Port: ");
- switch (ep->port) {
+ switch (link_usettings->base.port) {
case PORT_TP:
fprintf(stdout, "Twisted Pair\n");
break;
@@ -640,13 +741,13 @@ static int dump_ecmd(struct ethtool_cmd *ep)
fprintf(stdout, "Other\n");
break;
default:
- fprintf(stdout, "Unknown! (%i)\n", ep->port);
+ fprintf(stdout, "Unknown! (%i)\n", link_usettings->base.port);
break;
};
- fprintf(stdout, " PHYAD: %d\n", ep->phy_address);
+ fprintf(stdout, " PHYAD: %d\n", link_usettings->base.phy_address);
fprintf(stdout, " Transceiver: ");
- switch (ep->transceiver) {
+ switch (link_usettings->deprecated.transceiver) {
case XCVR_INTERNAL:
fprintf(stdout, "internal\n");
break;
@@ -659,17 +760,18 @@ static int dump_ecmd(struct ethtool_cmd *ep)
};
fprintf(stdout, " Auto-negotiation: %s\n",
- (ep->autoneg == AUTONEG_DISABLE) ?
+ (link_usettings->base.autoneg == AUTONEG_DISABLE) ?
"off" : "on");
- if (ep->port == PORT_TP) {
+ if (link_usettings->base.port == PORT_TP) {
fprintf(stdout, " MDI-X: ");
- if (ep->eth_tp_mdix_ctrl == ETH_TP_MDI) {
+ if (link_usettings->base.eth_tp_mdix_ctrl == ETH_TP_MDI) {
fprintf(stdout, "off (forced)\n");
- } else if (ep->eth_tp_mdix_ctrl == ETH_TP_MDI_X) {
+ } else if (link_usettings->base.eth_tp_mdix_ctrl
+ == ETH_TP_MDI_X) {
fprintf(stdout, "on (forced)\n");
} else {
- switch (ep->eth_tp_mdix) {
+ switch (link_usettings->base.eth_tp_mdix) {
case ETH_TP_MDI:
fprintf(stdout, "off");
break;
@@ -680,7 +782,8 @@ static int dump_ecmd(struct ethtool_cmd *ep)
fprintf(stdout, "Unknown");
break;
}
- if (ep->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
+ if (link_usettings->base.eth_tp_mdix_ctrl
+ == ETH_TP_MDI_AUTO)
fprintf(stdout, " (auto)");
fprintf(stdout, "\n");
}
@@ -1368,6 +1471,7 @@ static int dump_rxfhash(int fhash, u64 val)
static void dump_eeecmd(struct ethtool_eee *ep)
{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(link_mode);
fprintf(stdout, " EEE status: ");
if (!ep->supported) {
@@ -1389,9 +1493,16 @@ static void dump_eeecmd(struct ethtool_eee *ep)
else
fprintf(stdout, " disabled\n");
- dump_link_caps("Supported EEE", "", ep->supported, 1);
- dump_link_caps("Advertised EEE", "", ep->advertised, 1);
- dump_link_caps("Link partner advertised EEE", "", ep->lp_advertised, 1);
+ ethtool_link_mode_zero(link_mode);
+
+ link_mode[0] = ep->supported;
+ dump_link_caps("Supported EEE", "", link_mode, 1);
+
+ link_mode[0] = ep->advertised;
+ dump_link_caps("Advertised EEE", "", link_mode, 1);
+
+ link_mode[0] = ep->lp_advertised;
+ dump_link_caps("Link partner advertised EEE", "", link_mode, 1);
}
#define N_SOTS 7
@@ -2247,10 +2358,220 @@ static int do_sfeatures(struct cmd_context *ctx)
return 0;
}
-static int do_gset(struct cmd_context *ctx)
+static struct ethtool_link_usettings *
+__do_ioctl_glinksettings(struct cmd_context *ctx)
+{
+ int err;
+ struct {
+ struct ethtool_link_settings req;
+ __u32 link_mode_data[3*__ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
+ } ecmd;
+ struct ethtool_link_usettings *link_usettings;
+ unsigned int u32_offs;
+
+ /* Handshake with kernel to determine number of words for link
+ * mode bitmaps. When requested number of bitmap words is not
+ * the one expected by kernel, the latter returns the integer
+ * opposite of what it is expecting. We request length 0 below
+ * (aka. invalid bitmap length) to get this info.
+ */
+ memset(&ecmd, 0, sizeof(ecmd));
+ ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
+ err = send_ioctl(ctx, &ecmd);
+ if (err < 0)
+ return NULL;
+
+ /* see above: we expect a strictly negative value from kernel.
+ */
+ if (ecmd.req.link_mode_masks_nwords >= 0
+ || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
+ return NULL;
+
+ /* got the real ecmd.req.link_mode_masks_nwords,
+ * now send the real request
+ */
+ ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
+ ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
+ err = send_ioctl(ctx, &ecmd);
+ if (err < 0)
+ return NULL;
+
+ if (ecmd.req.link_mode_masks_nwords <= 0
+ || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
+ return NULL;
+
+ /* Convert to usettings struct */
+ link_usettings = calloc(1, sizeof(*link_usettings));
+ if (link_usettings == NULL)
+ return NULL;
+
+ /* keep transceiver 0 */
+ memcpy(&link_usettings->base, &ecmd.req, sizeof(link_usettings->base));
+
+ /* copy link mode bitmaps */
+ u32_offs = 0;
+ memcpy(link_usettings->link_modes.supported,
+ &ecmd.link_mode_data[u32_offs],
+ 4*ecmd.req.link_mode_masks_nwords);
+
+ u32_offs += ecmd.req.link_mode_masks_nwords;
+ memcpy(link_usettings->link_modes.advertising,
+ &ecmd.link_mode_data[u32_offs],
+ 4*ecmd.req.link_mode_masks_nwords);
+
+ u32_offs += ecmd.req.link_mode_masks_nwords;
+ memcpy(link_usettings->link_modes.lp_advertising,
+ &ecmd.link_mode_data[u32_offs],
+ 4*ecmd.req.link_mode_masks_nwords);
+
+ return link_usettings;
+}
+
+static int
+__do_ioctl_slinksettings(struct cmd_context *ctx,
+ const struct ethtool_link_usettings *link_usettings)
+{
+ struct {
+ struct ethtool_link_settings req;
+ __u32 link_mode_data[3*__ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
+ } ecmd;
+ unsigned int u32_offs;
+
+ /* refuse to send ETHTOOL_SLINKSETTINGS ioctl if
+ * link_usettings was retrieved with ETHTOOL_GSET
+ */
+ if (link_usettings->base.cmd != ETHTOOL_GLINKSETTINGS)
+ return -1;
+
+ /* refuse to send ETHTOOL_SLINKSETTINGS ioctl if deprecated fields
+ * were set
+ */
+ if (link_usettings->deprecated.transceiver)
+ return -1;
+
+ if (link_usettings->base.link_mode_masks_nwords <= 0)
+ return -1;
+
+ memcpy(&ecmd.req, &link_usettings->base, sizeof(ecmd.req));
+ ecmd.req.cmd = ETHTOOL_SLINKSETTINGS;
+
+ /* copy link mode bitmaps */
+ u32_offs = 0;
+ memcpy(&ecmd.link_mode_data[u32_offs],
+ link_usettings->link_modes.supported,
+ 4*ecmd.req.link_mode_masks_nwords);
+
+ u32_offs += ecmd.req.link_mode_masks_nwords;
+ memcpy(&ecmd.link_mode_data[u32_offs],
+ link_usettings->link_modes.advertising,
+ 4*ecmd.req.link_mode_masks_nwords);
+
+ u32_offs += ecmd.req.link_mode_masks_nwords;
+ memcpy(&ecmd.link_mode_data[u32_offs],
+ link_usettings->link_modes.lp_advertising,
+ 4*ecmd.req.link_mode_masks_nwords);
+
+ return send_ioctl(ctx, &ecmd);
+}
+
+static struct ethtool_link_usettings *
+__do_ioctl_gset(struct cmd_context *ctx)
{
int err;
struct ethtool_cmd ecmd;
+ struct ethtool_link_usettings *link_usettings;
+
+ memset(&ecmd, 0, sizeof(ecmd));
+ ecmd.cmd = ETHTOOL_GSET;
+ err = send_ioctl(ctx, &ecmd);
+ if (err < 0)
+ return NULL;
+
+ link_usettings = calloc(1, sizeof(*link_usettings));
+ if (link_usettings == NULL)
+ return NULL;
+
+ /* remember that ETHTOOL_GSET was used */
+ link_usettings->base.cmd = ETHTOOL_GSET;
+
+ link_usettings->base.link_mode_masks_nwords = 1;
+ link_usettings->link_modes.supported[0] = ecmd.supported;
+ link_usettings->link_modes.advertising[0] = ecmd.advertising;
+ link_usettings->link_modes.lp_advertising[0] = ecmd.lp_advertising;
+ link_usettings->base.speed = ethtool_cmd_speed(&ecmd);
+ link_usettings->base.duplex = ecmd.duplex;
+ link_usettings->base.port = ecmd.port;
+ link_usettings->base.phy_address = ecmd.phy_address;
+ link_usettings->deprecated.transceiver = ecmd.transceiver;
+ link_usettings->base.autoneg = ecmd.autoneg;
+ link_usettings->base.mdio_support = ecmd.mdio_support;
+ /* ignored (fully deprecated): maxrxpkt, maxtxpkt */
+ link_usettings->base.eth_tp_mdix = ecmd.eth_tp_mdix;
+ link_usettings->base.eth_tp_mdix_ctrl = ecmd.eth_tp_mdix_ctrl;
+
+ return link_usettings;
+}
+
+static bool ethtool_link_mode_is_backward_compatible(const u32 *mask)
+{
+ unsigned int i;
+
+ for (i = 1 ; i < __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32 ; ++i)
+ if (mask[i])
+ return false;
+
+ return true;
+}
+
+static int
+__do_ioctl_sset(struct cmd_context *ctx,
+ const struct ethtool_link_usettings *link_usettings)
+{
+ struct ethtool_cmd ecmd;
+
+ /* refuse to send ETHTOOL_SSET ioctl if link_usettings was
+ * retrieved with ETHTOOL_GLINKSETTINGS
+ */
+ if (link_usettings->base.cmd != ETHTOOL_GSET)
+ return -1;
+
+ if (link_usettings->base.link_mode_masks_nwords <= 0)
+ return -1;
+
+ /* refuse to sset if any bit > 31 is set */
+ if (!ethtool_link_mode_is_backward_compatible(
+ link_usettings->link_modes.supported))
+ return -1;
+ if (!ethtool_link_mode_is_backward_compatible(
+ link_usettings->link_modes.advertising))
+ return -1;
+ if (!ethtool_link_mode_is_backward_compatible(
+ link_usettings->link_modes.lp_advertising))
+ return -1;
+
+ memset(&ecmd, 0, sizeof(ecmd));
+ ecmd.cmd = ETHTOOL_SSET;
+
+ ecmd.supported = link_usettings->link_modes.supported[0];
+ ecmd.advertising = link_usettings->link_modes.advertising[0];
+ ecmd.lp_advertising = link_usettings->link_modes.lp_advertising[0];
+ ethtool_cmd_speed_set(&ecmd, link_usettings->base.speed);
+ ecmd.duplex = link_usettings->base.duplex;
+ ecmd.port = link_usettings->base.port;
+ ecmd.phy_address = link_usettings->base.phy_address;
+ ecmd.transceiver = link_usettings->deprecated.transceiver;
+ ecmd.autoneg = link_usettings->base.autoneg;
+ ecmd.mdio_support = link_usettings->base.mdio_support;
+ /* ignored (fully deprecated): maxrxpkt, maxtxpkt */
+ ecmd.eth_tp_mdix = link_usettings->base.eth_tp_mdix;
+ ecmd.eth_tp_mdix_ctrl = link_usettings->base.eth_tp_mdix_ctrl;
+ return send_ioctl(ctx, &ecmd);
+}
+
+static int do_gset(struct cmd_context *ctx)
+{
+ int err;
+ struct ethtool_link_usettings *link_usettings;
struct ethtool_wolinfo wolinfo;
struct ethtool_value edata;
int allfail = 1;
@@ -2260,10 +2581,12 @@ static int do_gset(struct cmd_context *ctx)
fprintf(stdout, "Settings for %s:\n", ctx->devname);
- ecmd.cmd = ETHTOOL_GSET;
- err = send_ioctl(ctx, &ecmd);
- if (err == 0) {
- err = dump_ecmd(&ecmd);
+ link_usettings = __do_ioctl_glinksettings(ctx);
+ if (link_usettings == NULL)
+ link_usettings = __do_ioctl_gset(ctx);
+ if (link_usettings != NULL) {
+ err = dump_link_usettings(link_usettings);
+ free(link_usettings);
if (err)
return err;
allfail = 0;
@@ -2322,8 +2645,10 @@ static int do_sset(struct cmd_context *ctx)
int autoneg_wanted = -1;
int phyad_wanted = -1;
int xcvr_wanted = -1;
- int full_advertising_wanted = -1;
- int advertising_wanted = -1;
+ u32 *full_advertising_wanted = NULL;
+ u32 *advertising_wanted = NULL;
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(_mask_full_advertising_wanted);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(_mask_advertising_wanted);
int gset_changed = 0; /* did anything in GSET change? */
u32 wol_wanted = 0;
int wol_change = 0;
@@ -2337,7 +2662,7 @@ static int do_sset(struct cmd_context *ctx)
int argc = ctx->argc;
char **argp = ctx->argp;
int i;
- int err;
+ int err = 0;
for (i = 0; i < ARRAY_SIZE(flags_msglvl); i++)
flag_to_cmdline_info(flags_msglvl[i].name,
@@ -2411,7 +2736,12 @@ static int do_sset(struct cmd_context *ctx)
i += 1;
if (i >= argc)
exit_bad_args();
- full_advertising_wanted = get_int(argp[i], 16);
+ if (parse_hex_u32_bitmap(
+ argp[i],
+ __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBITS,
+ _mask_full_advertising_wanted))
+ exit_bad_args();
+ full_advertising_wanted = _mask_full_advertising_wanted;
} else if (!strcmp(argp[i], "phyad")) {
gset_changed = 1;
i += 1;
@@ -2468,75 +2798,89 @@ static int do_sset(struct cmd_context *ctx)
}
}
- if (full_advertising_wanted < 0) {
+ if (full_advertising_wanted == NULL) {
/* User didn't supply a full advertisement bitfield:
* construct one from the specified speed and duplex.
*/
+ int adv_bit = -1;
+
if (speed_wanted == SPEED_10 && duplex_wanted == DUPLEX_HALF)
- advertising_wanted = ADVERTISED_10baseT_Half;
+ adv_bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT;
else if (speed_wanted == SPEED_10 &&
duplex_wanted == DUPLEX_FULL)
- advertising_wanted = ADVERTISED_10baseT_Full;
+ adv_bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT;
else if (speed_wanted == SPEED_100 &&
duplex_wanted == DUPLEX_HALF)
- advertising_wanted = ADVERTISED_100baseT_Half;
+ adv_bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT;
else if (speed_wanted == SPEED_100 &&
duplex_wanted == DUPLEX_FULL)
- advertising_wanted = ADVERTISED_100baseT_Full;
+ adv_bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT;
else if (speed_wanted == SPEED_1000 &&
duplex_wanted == DUPLEX_HALF)
- advertising_wanted = ADVERTISED_1000baseT_Half;
+ adv_bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT;
else if (speed_wanted == SPEED_1000 &&
duplex_wanted == DUPLEX_FULL)
- advertising_wanted = ADVERTISED_1000baseT_Full;
+ adv_bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT;
else if (speed_wanted == SPEED_2500 &&
duplex_wanted == DUPLEX_FULL)
- advertising_wanted = ADVERTISED_2500baseX_Full;
+ adv_bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT;
else if (speed_wanted == SPEED_10000 &&
duplex_wanted == DUPLEX_FULL)
- advertising_wanted = ADVERTISED_10000baseT_Full;
- else
- /* auto negotiate without forcing,
- * all supported speed will be assigned below
- */
- advertising_wanted = 0;
+ adv_bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT;
+
+ if (adv_bit >= 0) {
+ advertising_wanted = _mask_advertising_wanted;
+ ethtool_link_mode_zero(advertising_wanted);
+ ethtool_link_mode_set_bit(
+ adv_bit, advertising_wanted);
+ }
+ /* otherwise: auto negotiate without forcing,
+ * all supported speed will be assigned below
+ */
}
if (gset_changed) {
- struct ethtool_cmd ecmd;
+ struct ethtool_link_usettings *link_usettings;
- ecmd.cmd = ETHTOOL_GSET;
- err = send_ioctl(ctx, &ecmd);
- if (err < 0) {
+ link_usettings = __do_ioctl_glinksettings(ctx);
+ if (link_usettings == NULL)
+ link_usettings = __do_ioctl_gset(ctx);
+ if (link_usettings == NULL) {
perror("Cannot get current device settings");
+ err = -1;
} else {
/* Change everything the user specified. */
if (speed_wanted != -1)
- ethtool_cmd_speed_set(&ecmd, speed_wanted);
+ link_usettings->base.speed = speed_wanted;
if (duplex_wanted != -1)
- ecmd.duplex = duplex_wanted;
+ link_usettings->base.duplex = duplex_wanted;
if (port_wanted != -1)
- ecmd.port = port_wanted;
+ link_usettings->base.port = port_wanted;
if (mdix_wanted != -1) {
/* check driver supports MDI-X */
- if (ecmd.eth_tp_mdix_ctrl != ETH_TP_MDI_INVALID)
- ecmd.eth_tp_mdix_ctrl = mdix_wanted;
+ if (link_usettings->base.eth_tp_mdix_ctrl
+ != ETH_TP_MDI_INVALID)
+ link_usettings->base.eth_tp_mdix_ctrl
+ = mdix_wanted;
else
- fprintf(stderr, "setting MDI not supported\n");
+ fprintf(stderr,
+ "setting MDI not supported\n");
}
if (autoneg_wanted != -1)
- ecmd.autoneg = autoneg_wanted;
+ link_usettings->base.autoneg = autoneg_wanted;
if (phyad_wanted != -1)
- ecmd.phy_address = phyad_wanted;
+ link_usettings->base.phy_address = phyad_wanted;
if (xcvr_wanted != -1)
- ecmd.transceiver = xcvr_wanted;
+ link_usettings->deprecated.transceiver
+ = xcvr_wanted;
/* XXX If the user specified speed or duplex
* then we should mask the advertised modes
* accordingly. For now, warn that we aren't
* doing that.
*/
if ((speed_wanted != -1 || duplex_wanted != -1) &&
- ecmd.autoneg && advertising_wanted == 0) {
+ link_usettings->base.autoneg &&
+ advertising_wanted == NULL) {
fprintf(stderr, "Cannot advertise");
if (speed_wanted >= 0)
fprintf(stderr, " speed %d",
@@ -2548,37 +2892,56 @@ static int do_sset(struct cmd_context *ctx)
fprintf(stderr, "\n");
}
if (autoneg_wanted == AUTONEG_ENABLE &&
- advertising_wanted == 0) {
+ advertising_wanted == NULL) {
+ unsigned int i;
+
/* Auto negotiation enabled, but with
* unspecified speed and duplex: enable all
* supported speeds and duplexes.
*/
- ecmd.advertising =
- (ecmd.advertising &
- ~ALL_ADVERTISED_MODES) |
- (ALL_ADVERTISED_MODES & ecmd.supported);
+ ethtool_link_mode_for_each_u32(i) {
+ u32 sup = link_usettings->link_modes.supported[i];
+ u32 *adv = link_usettings->link_modes.advertising + i;
+
+ *adv = ((*adv & ~all_advertised_modes[i])
+ | (sup & all_advertised_modes[i]));
+ }
/* If driver supports unknown flags, we cannot
* be sure that we enable all link modes.
*/
- if ((ecmd.supported & ALL_ADVERTISED_FLAGS) !=
- ecmd.supported) {
- fprintf(stderr, "Driver supports one "
- "or more unknown flags\n");
+ ethtool_link_mode_for_each_u32(i) {
+ u32 sup = link_usettings->link_modes.supported[i];
+
+ if ((sup & all_advertised_flags[i]) != sup) {
+ fprintf(stderr, "Driver supports one or more unknown flags\n");
+ break;
+ }
}
- } else if (advertising_wanted > 0) {
+ } else if (advertising_wanted != NULL) {
+ unsigned int i;
+
/* Enable all requested modes */
- ecmd.advertising =
- (ecmd.advertising &
- ~ALL_ADVERTISED_MODES) |
- advertising_wanted;
- } else if (full_advertising_wanted > 0) {
- ecmd.advertising = full_advertising_wanted;
+ ethtool_link_mode_for_each_u32(i) {
+ u32 *adv = link_usettings->link_modes.advertising + i;
+
+ *adv = ((*adv & ~all_advertised_modes[i])
+ | advertising_wanted[i]);
+ }
+ } else if (full_advertising_wanted != NULL) {
+ ethtool_link_mode_copy(
+ link_usettings->link_modes.advertising,
+ full_advertising_wanted);
}
/* Try to perform the update. */
- ecmd.cmd = ETHTOOL_SSET;
- err = send_ioctl(ctx, &ecmd);
+ if (link_usettings->base.cmd == ETHTOOL_GLINKSETTINGS)
+ err = __do_ioctl_slinksettings(ctx,
+ link_usettings);
+ else
+ err = __do_ioctl_sset(ctx,
+ link_usettings);
+ free(link_usettings);
if (err < 0)
perror("Cannot set new settings");
}
@@ -4230,6 +4593,8 @@ int main(int argc, char **argp)
struct cmd_context ctx;
int k;
+ init_global_link_mode_masks();
+
/* Skip command name */
argp++;
argc--;
diff --git a/internal.h b/internal.h
index e98f532..5e78b5c 100644
--- a/internal.h
+++ b/internal.h
@@ -12,6 +12,7 @@
#ifdef HAVE_CONFIG_H
#include "ethtool-config.h"
#endif
+#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -122,6 +123,72 @@ static inline int test_bit(unsigned int nr, const unsigned long *addr)
ETH_FLAG_TXVLAN | ETH_FLAG_NTUPLE | \
ETH_FLAG_RXHASH)
+/* internal API for link mode bitmap interaction with kernel. */
+
+#define __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32 \
+ (SCHAR_MAX)
+#define __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBITS \
+ (32*__ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32)
+#define __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES \
+ (4*__ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32)
+#define __ETHTOOL_DECLARE_LINK_MODE_MASK(name) \
+ u32 name[__ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]
+
+struct ethtool_link_usettings {
+ struct {
+ __u8 transceiver;
+ } deprecated;
+ struct ethtool_link_settings base;
+ struct {
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
+ } link_modes;
+};
+
+#define ethtool_link_mode_for_each_u32(index) \
+ for ((index) = 0 ; \
+ (index) < __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32 ; \
+ ++(index))
+
+static inline void ethtool_link_mode_zero(u32 *dst)
+{
+ memset(dst, 0, __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES);
+}
+
+static inline bool ethtool_link_mode_is_empty(const u32 *mask)
+{
+ unsigned int i;
+
+ ethtool_link_mode_for_each_u32(i)
+ {
+ if (mask[i] != 0)
+ return false;
+ }
+
+ return true;
+}
+
+static inline void ethtool_link_mode_copy(u32 *dst, const u32 *src)
+{
+ memcpy(dst, src, __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES);
+}
+
+static inline int ethtool_link_mode_test_bit(unsigned int nr, const u32 *mask)
+{
+ if (nr >= __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBITS)
+ return !!0;
+ return !!(mask[nr / 32] & (1 << (nr % 32)));
+}
+
+static inline int ethtool_link_mode_set_bit(unsigned int nr, u32 *mask)
+{
+ if (nr >= __ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBITS)
+ return -1;
+ mask[nr / 32] |= (1 << (nr % 32));
+ return 0;
+}
+
/* Context for sub-commands */
struct cmd_context {
const char *devname; /* net device name */
diff --git a/test-cmdline.c b/test-cmdline.c
index 2fd7cbb..a94edea 100644
--- a/test-cmdline.c
+++ b/test-cmdline.c
@@ -37,7 +37,20 @@ static struct test_case {
{ 1, "--change devname autoneg foo" },
{ 1, "-s devname autoneg" },
{ 0, "--change devname advertise 0x1" },
+ { 0, "--change devname advertise 0xf" },
+ { 0, "--change devname advertise 0Xf" },
+ { 0, "--change devname advertise 1" },
+ { 0, "--change devname advertise f" },
+ { 0, "--change devname advertise 01" },
+ { 0, "--change devname advertise 0f" },
+ { 0, "--change devname advertise 0xfffffffffffffffffffffffffffffffff" },
+ { 0, "--change devname advertise fffffffffffffffffffffffffffffffff" },
+ { 0, "--change devname advertise 0x0000fffffffffffffffffffffffffffff" },
+ { 0, "--change devname advertise 0000fffffffffffffffffffffffffffff" },
+ { 1, "-s devname advertise" },
+ { 1, "-s devname advertise 0x" },
{ 1, "-s devname advertise foo" },
+ { 1, "-s devname advertise 0xfoo" },
{ 1, "--change devname advertise" },
{ 0, "-s devname phyad 1" },
{ 1, "--change devname phyad foo" },
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* [ethtool PATCH v7 2/2] ethtool: use netlink socket when AF_INET not available
From: David Decotigny @ 2016-05-02 17:00 UTC (permalink / raw)
To: netdev
Cc: Jeff Garzik, Ben Hutchings, David Miller, Vidya Sagar Ravipati,
Joe Perches, David Decotigny
In-Reply-To: <1462208411-114371-1-git-send-email-ddecotig@gmail.com>
From: David Decotigny <decot@googlers.com>
To benefit from this, kernel commit 025c68186e07 ("netlink: add support
for NIC driver ioctls") is needed.
Signed-off-by: David Decotigny <decot@googlers.com>
---
configure.ac | 2 +-
ethtool.c | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 3105415..47d2a0f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,7 +15,7 @@ AM_PROG_CC_C_O
dnl Checks for libraries.
dnl Checks for header files.
-AC_CHECK_HEADERS(sys/ioctl.h)
+AC_CHECK_HEADERS(sys/ioctl.h linux/netlink.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_MSG_CHECKING([whether <linux/types.h> defines big-endian types])
diff --git a/ethtool.c b/ethtool.c
index cb3d971..314b1b8 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -42,6 +42,9 @@
#include <arpa/inet.h>
#include <linux/sockios.h>
+#ifdef HAVE_LINUX_NETLINK_H
+# include <linux/netlink.h>
+#endif
#ifndef MAX_ADDR_LEN
#define MAX_ADDR_LEN 32
@@ -4645,6 +4648,10 @@ opt_found:
/* Open control socket. */
ctx.fd = socket(AF_INET, SOCK_DGRAM, 0);
+#ifdef HAVE_LINUX_NETLINK_H
+ if (ctx.fd < 0)
+ ctx.fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
+#endif
if (ctx.fd < 0) {
perror("Cannot get control socket");
return 70;
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* Re: [PATCH v2] rtlwifi: Fix logic error in enter/exit power-save mode
From: Larry Finger @ 2016-05-02 17:00 UTC (permalink / raw)
To: Wang YanQing, kvalo, chaoming_li, linux-wireless, netdev,
linux-kernel
In-Reply-To: <20160502163835.GA10925@udknight>
On 05/02/2016 11:38 AM, Wang YanQing wrote:
> In commit a269913c52ad ("rtlwifi: Rework rtl_lps_leave() and
> rtl_lps_enter() to use work queue"), the tests for enter/exit
> power-save mode were inverted. With this change applied, the
> wifi connection becomes much more stable.
>
> Fixes: a269913c52ad ("rtlwifi: Rework rtl_lps_leave() and rtl_lps_enter() to use work queue")
> Signed-off-by: Wang YanQing <udknight@gmail.com>
> CC: Stable <stable@vger.kernel.org> [3.10+]
> ---
> Hi, Larry!
>
> Because commit a269913c52ad is the first commit bring this problem,
> so maybe use above commit message is ok, right? And stable kernels
> 3.10-3.18 don't have commit fd09ff958777, but have a269913c52ad.
>
> Thanks for suggestion concerning to good subject and commit message
> writing, it is harder than coding sometimes:)
>
> Changes:
> v1-v2:
> 1: Fix subject and commit message.
Yes, I agree that the commit message is hard.
Acked-by: Larry Finger <Larry.Finger@lwfinger.net>
Thanks,
Larry
>
> drivers/net/wireless/realtek/rtlwifi/base.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
> index c74eb13..264466f 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/base.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/base.c
> @@ -1660,9 +1660,9 @@ void rtl_watchdog_wq_callback(void *data)
> if (((rtlpriv->link_info.num_rx_inperiod +
> rtlpriv->link_info.num_tx_inperiod) > 8) ||
> (rtlpriv->link_info.num_rx_inperiod > 2))
> - rtl_lps_enter(hw);
> - else
> rtl_lps_leave(hw);
> + else
> + rtl_lps_enter(hw);
> }
>
> rtlpriv->link_info.num_rx_inperiod = 0;
>
^ permalink raw reply
* Re: [net PATCH 1/2] net: Disable segmentation if checksumming is not supported
From: Tom Herbert @ 2016-05-02 17:07 UTC (permalink / raw)
To: Alexander Duyck
Cc: Alexander Duyck, Linux Kernel Network Developers, Or Gerlitz,
David S. Miller
In-Reply-To: <CAKgT0UdaaXNX=G052vjC+JVZG8MGyHKPMMxK-U5Zgn8FiENNPg@mail.gmail.com>
On Mon, May 2, 2016 at 9:48 AM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Mon, May 2, 2016 at 9:33 AM, Tom Herbert <tom@herbertland.com> wrote:
>> On Mon, May 2, 2016 at 9:25 AM, Alexander Duyck <aduyck@mirantis.com> wrote:
>>> In the case of the mlx4 and mlx5 driver they do not support IPv6 checksum
>>> offload for tunnels. With this being the case we should disable GSO in
>>> addition to the checksum offload features when we find that a device cannot
>>> perform a checksum on a given packet type.
>>>
>> I'm not sure I understand this. If device can't support checksum
>> offload for tunnels doesn't that mean we have to do the checksum on
>> host regardless of whether GSO is being done?
>
> The use of the term GSO here might be the confusing part. Basically
> the issue is the hardware advertises it can do TSO for IPv4 on
> encapsulated frames, however it doesn't indicate it can do IPv6
> checksum offload. So what ends up happening is that in the case of a
> v4 over v6 tunnel we were going through validate_xmit_skb which will
> check things in netif_skb_features and come out supporting the TSO but
> no checksums. As a result we would fall through and hit
> skb_checksum_help and trigger the warn on in there because we had TSO
> requested even though we couldn't do the checksum.
>
> Basically I am just extending the kind of logic we have in
> netdev_fix_features so that if we cannot support checksumming the
> frame then we cannot support segmenting it.
>
Thanks for the explanation. We need to drive things so that all the
encapsulation combinations (v4/v4, v4/v6, v6/v4, v6/v6) are supported
by HW TSO if any of them are supported by a device. Maybe we should
still have some sort of warning message that HW is broken for some
combination (like it apparently it is for mlnx4)?
Tom
> - Alex
^ permalink raw reply
* Re: [PATCH net-next] fq_codel: add batch ability to fq_codel_drop()
From: Jesper Dangaard Brouer @ 2016-05-02 17:15 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev, Dave Taht, Jonathan Morton, brouer
In-Reply-To: <1462205571.5535.253.camel@edumazet-glaptop3.roam.corp.google.com>
On Mon, 02 May 2016 09:12:51 -0700
Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Mon, 2016-05-02 at 18:00 +0200, Jesper Dangaard Brouer wrote:
>
> > It is not that complicated, inside kfree_skb_list(), we just call
> > skb_release_all(skb) on each SKB first, and then bulk free the SKB's
> > themselves in the end. Example see, _kfree_skb_defer().
> >
> > The question is where to store the SKB array needed by kmem_cache_free_bulk.
> >
> > The easy option is just to use the stack of kfree_skb_list(), but we
> > have to be careful about the stack size, it might not be so good
> > because skb_release_all() can be deep and via skb_release_data() invoke
> > kfree_skb_list() a second time.
> >
>
> It sounds you are reinventing the wheel ;)
>
> If drivers use napi_consume_skb(), qdisc should be able to use it the
> same, since BH are disabled in their ->enqueue()/->dequeue() handlers.
Oh, yes. That is true, we can just use napi_consume_skb(). Should we
have a napi_kfree_skb(), to get the trace_kfree_skb() correct?
> This would be a separate patch of course.
>
> This fq_codel fix might need to be backported.
Agreed. I ACK your patch.
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
Author of http://www.iptv-analyzer.org
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [net PATCH 1/2] net: Disable segmentation if checksumming is not supported
From: Alexander Duyck @ 2016-05-02 17:20 UTC (permalink / raw)
To: Tom Herbert
Cc: Alexander Duyck, Linux Kernel Network Developers, Or Gerlitz,
David S. Miller
In-Reply-To: <CALx6S36Y8BD2wk-FOxExf50Bs1Lq8_m-9Pxrf7E+0FOaC+C+Ow@mail.gmail.com>
On Mon, May 2, 2016 at 10:07 AM, Tom Herbert <tom@herbertland.com> wrote:
> On Mon, May 2, 2016 at 9:48 AM, Alexander Duyck
> <alexander.duyck@gmail.com> wrote:
>> On Mon, May 2, 2016 at 9:33 AM, Tom Herbert <tom@herbertland.com> wrote:
>>> On Mon, May 2, 2016 at 9:25 AM, Alexander Duyck <aduyck@mirantis.com> wrote:
>>>> In the case of the mlx4 and mlx5 driver they do not support IPv6 checksum
>>>> offload for tunnels. With this being the case we should disable GSO in
>>>> addition to the checksum offload features when we find that a device cannot
>>>> perform a checksum on a given packet type.
>>>>
>>> I'm not sure I understand this. If device can't support checksum
>>> offload for tunnels doesn't that mean we have to do the checksum on
>>> host regardless of whether GSO is being done?
>>
>> The use of the term GSO here might be the confusing part. Basically
>> the issue is the hardware advertises it can do TSO for IPv4 on
>> encapsulated frames, however it doesn't indicate it can do IPv6
>> checksum offload. So what ends up happening is that in the case of a
>> v4 over v6 tunnel we were going through validate_xmit_skb which will
>> check things in netif_skb_features and come out supporting the TSO but
>> no checksums. As a result we would fall through and hit
>> skb_checksum_help and trigger the warn on in there because we had TSO
>> requested even though we couldn't do the checksum.
>>
>> Basically I am just extending the kind of logic we have in
>> netdev_fix_features so that if we cannot support checksumming the
>> frame then we cannot support segmenting it.
>>
> Thanks for the explanation. We need to drive things so that all the
> encapsulation combinations (v4/v4, v4/v6, v6/v4, v6/v6) are supported
> by HW TSO if any of them are supported by a device. Maybe we should
> still have some sort of warning message that HW is broken for some
> combination (like it apparently it is for mlnx4)?
The problem is the user could end up switching features on/off via
ethtool to create the same kind of situation. Generally the v4/v6 mix
and match is going to be a more difficult case to deal with. By
adding the check to the VXLAN features check and updating the checksum
check to disable GSO I think we should have most if not all cases
covered.
Also as far as the mlx4 the Mellanox guys are looking into it because
they were sure the part is supposed to be able to support an outer
IPv6 header so we may see something int he future come out to address
that. Really what I would like to see us get away from is having
hardware to do any tunnel parsing for Tx which is where I believe this
issue lies since on the Rx side the mlx4 doesn't seem to recognize
tunnels encapsulated in IPv6 since it doesn't perform an inner
checksum offload.
- Alex
^ permalink raw reply
* Re: [PATCHv2 bluetooth-next 00/10] 6lowpan: introduce basic 6lowpan-nd
From: Marcel Holtmann @ 2016-05-02 17:25 UTC (permalink / raw)
To: Alexander Aring, David S. Miller
Cc: linux-wpan-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
Jukka Rissanen, hannes-tFNcAqjVMyqKXQKiL6tip0B+6BGkLq7r,
Stefan Schmidt, mcr-SWp7JaYWvAQV+D8aMU/kSg, Werner Almesberger,
Linux Bluetooth, Network Development, Alexey Kuznetsov,
James Morris, Hideaki YOSHIFUJI, Patrick McHardy
In-Reply-To: <1461140382-4784-1-git-send-email-aar-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Hi Dave,
> this patch series introduces a layer for IPv6 neighbour discovery. At first
> it introduce the "ndisc_ops" to run a different handling for recv/send of
> NA/NS messages. The use case for such ndisc operation is RFC 6775 [0].
> Which describes a different neighbour discovery handling for 6LoWPAN networks.
>
> I didn't implement RFC 6775 in this patch series, but introduce callback
> structure for replace different functions in ndisc implementation might be
> the right direction.
>
> Another use case would be RFC 7400 [1] which describes a new option field to
> getting capabilities of 6LoWPAN next header compression methods.
>
> What I implemented is a necessary functionality to handle short address for
> 802.15.4 6LoWPAN networks. The L2-Layer "802.15.4" can have two different
> link-layer addresses which can be used mixed at the same time inside 802.15.4
> networks. To deal with such behaviour in ndisc, it is defined at RFC 4944 [2].
> The bad news is, that I saw different handling of such handling. What Linux
> will do is to add two source/target address information option fields, each
> with different length, if short address is valid (can also not be given).
> Example:
>
> - WPAN interface address settings
> - extended addr (must always be there)
> - short addr (0xfffe or 0xffff -> invalid)
>
> Will add an extended addr to source/target address information option field.
> If short addr is in some valid range, then both address will be added to
> the option fields. Indicated are these different address types by the length
> field (extended -> length=2, short -> length=1), according to [1].
>
> The tested 6LoWPAN implementation (RIOT-OS) allows only one source/target
> option field which is short XOR extended, otherwise it will be dropped.
> There is some lack of information there [2] and I don't know how do deal with
> it right, maybe we need to update the implementation there if it's really
> wrong.
>
> To save such information for each neighbour we use the already implemented
> neighbour private data which some casting strategy for 6LoWPAN and 6LoWPAN
> link-layer specific data e.g. 802.15.4 short address handling.
>
> Additional I implemented to add 6CO to the is_useropt callback in case of
> 6LoWPAN interface. The 6CO option will currently parsed in userspace which
> are placed in RA-Messages.
>
> The ndisc_ops are not finished yet, of course we need handling for RS messages
> to place the 802.15.4 short address there as well and then also processing
> of RA messages for the 802.15.4 SLLAO option field.
>
> - Alex
>
> [0] https://tools.ietf.org/html/rfc6775
> [1] https://tools.ietf.org/html/rfc7400#section-3.3
> [2] https://tools.ietf.org/html/rfc4944#section-8
>
> Cc: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
> Cc: Alexey Kuznetsov <kuznet-v/Mj1YrvjDBInbfyfbPRSQ@public.gmane.org>
> Cc: James Morris <jmorris-gx6/JNMH7DfYtjvyW6yDsg@public.gmane.org>
> Cc: Hideaki YOSHIFUJI <yoshfuji-VfPWfsRibaP+Ru+s062T9g@public.gmane.org>
> Cc: Patrick McHardy <kaber-dcUjhNyLwpNeoWH0uzbU5w@public.gmane.org>
>
> changes since v2:
> - replace #ifdef CONFIG_IPV6 to #if IS_ENABLED(...)
> - replace #ifdef CONFIG_IEEE802154... to #if IS_ENABLED(...)
> - add more #if IS_ENABLED(CONFIG_IPV6) in ndisc.h
>
> Alexander Aring (10):
> 6lowpan: add private neighbour data
> 6lowpan: add 802.15.4 short addr slaac
> 6lowpan: remove ipv6 module request
> ndisc: add addr_len parameter to ndisc_opt_addr_space
> ndisc: add addr_len parameter to ndisc_opt_addr_data
> ndisc: add addr_len parameter to ndisc_fill_addr_option
> ipv6: introduce neighbour discovery ops
> ipv6: export ndisc functions
> 6lowpan: introduce 6lowpan-nd
> 6lowpan: add support for 802.15.4 short addr handling
>
> include/linux/netdevice.h | 6 +-
> include/net/6lowpan.h | 24 ++
> include/net/addrconf.h | 3 +
> include/net/ndisc.h | 124 ++++++++-
> net/6lowpan/6lowpan_i.h | 2 +
> net/6lowpan/Makefile | 2 +-
> net/6lowpan/core.c | 50 +++-
> net/6lowpan/iphc.c | 167 +++++++++--
> net/6lowpan/ndisc.c | 633 ++++++++++++++++++++++++++++++++++++++++++
> net/bluetooth/6lowpan.c | 2 +
> net/ieee802154/6lowpan/core.c | 12 +
> net/ieee802154/6lowpan/tx.c | 107 ++++---
> net/ipv6/addrconf.c | 7 +-
> net/ipv6/ndisc.c | 132 +++++----
> net/ipv6/route.c | 4 +-
> 15 files changed, 1117 insertions(+), 158 deletions(-)
> create mode 100644 net/6lowpan/ndisc.c
is there a chance that we get input into this patch set? I wonder also if it would be acceptable to take this through bluetooth-next or should it better go straight into net-next?
Regards
Marcel
^ permalink raw reply
* Re: VRF_DEVICE integration plan
From: David Ahern @ 2016-05-02 17:43 UTC (permalink / raw)
To: Elluru, Krishna Mohan, netdev@vger.kernel.org
Cc: Kumara, Shantha (HP Networking), Govindan Nair, Anoop
In-Reply-To: <CS1PR84MB0072AC62E9EBCC5A42E33952CA650@CS1PR84MB0072.NAMPRD84.PROD.OUTLOOK.COM>
On 4/28/16 11:16 AM, Elluru, Krishna Mohan wrote:
>
> I posted a few bug fix patches a week or two ago. Not sure what the
> status is with respect to 4.3 - 4.5 trees.
>
> MOHAN> Sure. Are those patches sent over netdev mailer list?
yes. All patches for VRF - kernel and iproute2 - are sent to netdev.
> MOHAN> sorry for not being clear. My ask was, to create a namespace we need cap_admin privileges currently, but your earlier mails suggested that we should be able to configure/create vrf device with net_admin capabilities. Is this support present /expected to be added soon?
VRF is implemented using a netdevice. As such the ability to create one
requires the same permissions as creating any other netdevice
(CAP_NET_ADMIN).
>> 5. Is there a possibility of enabling secondary level lookup, to give a leak functionality to parent route table from device local route table? I tested with veth pair, configured one as default gateway, it is possible to forward traffic b/w the interfaces, looking for cleaner method.
>
> Are you referring to inter-vrf routing? See slide 27
> http://www.netdevconf.org/1.1/proceedings/slides/ahern-vrf-tutorial.pdf
> Full lookup in VRF table
> ▪ ip route add table vrf-red 1.1.1.0/24 dev vrf-green
> MOHAN> In slide 27 above shows inter vrf routing, requirement is to use current namespace global route table if the ip lookup fails in vrf-device routing table.
> Reference: https://www.juniper.net/techpubs/en_US/junose16.1/topics/task/configuration/mbgp-secondary-routing-table-search.html
One solution is to create a VRF device that is associated with the main
table and then use an inter-vrf route to jump to the main table.
VRF tables do need a default route (e.g., unreachable with high metric
value) else the FIB lookups will proceed to the next table which is most
likely not what you want.
David
^ permalink raw reply
* [PATCH net-next] net: add __sock_wfree() helper
From: Eric Dumazet @ 2016-05-02 17:56 UTC (permalink / raw)
To: David Miller; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
Hosts sending lot of ACK packets exhibit high sock_wfree() cost
because of cache line miss to test SOCK_USE_WRITE_QUEUE
We could move this flag close to sk_wmem_alloc but it is better
to perform the atomic_sub_and_test() on a clean cache line,
as it avoid one extra bus transaction.
skb_orphan_partial() can also have a fast track for packets that either
are TCP acks, or already went through another skb_orphan_partial()
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/net/sock.h | 1 +
net/core/sock.c | 24 ++++++++++++++++++++++++
net/ipv4/tcp_output.c | 2 +-
3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 3df778ccaa820b00b4038feedae30cd444e9a212..9be2ffb4b8fcf54cc9c8bd73628dd7572b1d783d 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1434,6 +1434,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority);
struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
gfp_t priority);
+void __sock_wfree(struct sk_buff *skb);
void sock_wfree(struct sk_buff *skb);
void skb_orphan_partial(struct sk_buff *skb);
void sock_rfree(struct sk_buff *skb);
diff --git a/net/core/sock.c b/net/core/sock.c
index e16a5db853c6f455b0ac826744d0ee5e96a44863..e1151f11eb4aa0a5afa95bfee9d00a85c4d50af6 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1655,6 +1655,17 @@ void sock_wfree(struct sk_buff *skb)
}
EXPORT_SYMBOL(sock_wfree);
+/* This variant of sock_wfree() is used by TCP,
+ * since it sets SOCK_USE_WRITE_QUEUE.
+ */
+void __sock_wfree(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+
+ if (atomic_sub_and_test(skb->truesize, &sk->sk_wmem_alloc))
+ __sk_free(sk);
+}
+
void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
{
skb_orphan(skb);
@@ -1677,8 +1688,21 @@ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
}
EXPORT_SYMBOL(skb_set_owner_w);
+/* This helper is used by netem, as it can hold packets in its
+ * delay queue. We want to allow the owner socket to send more
+ * packets, as if they were already TX completed by a typical driver.
+ * But we also want to keep skb->sk set because some packet schedulers
+ * rely on it (sch_fq for example). So we set skb->truesize to a small
+ * amount (1) and decrease sk_wmem_alloc accordingly.
+ */
void skb_orphan_partial(struct sk_buff *skb)
{
+ /* If this skb is a TCP pure ACK or already went here,
+ * we have nothing to do. 2 is already a very small truesize.
+ */
+ if (skb->truesize <= 2)
+ return;
+
/* TCP stack sets skb->ooo_okay based on sk_wmem_alloc,
* so we do not completely orphan skb, but transfert all
* accounted bytes but one, to avoid unexpected reorders.
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 1a487ff95d4c0572737e4f972666229f12ef1e08..778ac8f2d84be389478e4d92335e1979482b3817 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -949,7 +949,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
skb_orphan(skb);
skb->sk = sk;
- skb->destructor = skb_is_tcp_pure_ack(skb) ? sock_wfree : tcp_wfree;
+ skb->destructor = skb_is_tcp_pure_ack(skb) ? __sock_wfree : tcp_wfree;
skb_set_hash_from_sk(skb, sk);
atomic_add(skb->truesize, &sk->sk_wmem_alloc);
^ permalink raw reply related
* Re: [PATCH] Bluetooth: Use hci_conn_hash_lookup_le
From: Johan Hedberg @ 2016-05-02 18:02 UTC (permalink / raw)
To: Julia Lawall
Cc: Marcel Holtmann, kernel-janitors, Gustavo Padovan,
David S. Miller, linux-bluetooth, netdev, linux-kernel
In-Reply-To: <1461957760-753-1-git-send-email-Julia.Lawall@lip6.fr>
Hi,
On Fri, Apr 29, 2016, Julia Lawall wrote:
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -4773,7 +4773,8 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
> conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
> &cp->addr.bdaddr);
> else
> - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
> + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
> + cp->addr.type);
I don't think is is correct. There are two possible domains for address
types: the user space-facing interface that has three values: BR/EDR, LE
public & LE random, and the internal one which maps to HCI that has two
values: random or public. You'd need to convert from the former to the
latter when making the lookup call, i.e:
conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
Johan
^ permalink raw reply
* Re: [PATCH net 1/2] RDS:TCP: Synchronize rds_tcp_accept_one with rds_send_xmit when resetting t_sock
From: Santosh Shilimkar @ 2016-05-02 18:05 UTC (permalink / raw)
To: Sowmini Varadhan; +Cc: netdev, rds-devel, davem
In-Reply-To: <20160502163715.GD20517@oracle.com>
On 5/2/2016 9:37 AM, Sowmini Varadhan wrote:
> On (05/02/16 09:20), Santosh Shilimkar wrote:
>>> rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING);
>>> + if (rs_tcp->t_sock) {
>>> + /* Need to resolve a duelling SYN between peers.
>>> + * We have an outstanding SYN to this peer, which may
>>> + * potentially have transitioned to the RDS_CONN_UP state,
>>> + * so we must quiesce any send threads before resetting
>>> + * c_transport_data.
>>> + */
>>> + wait_event(conn->c_waitq,
>>> + !test_bit(RDS_IN_XMIT, &conn->c_flags));
>> Would it be good to check the return value of rds_conn_transition()
>> since if CONN is already UP above will fail and then send message
>> might again race and we will let message through even though passive
>> hasn't finished its connection.
>
> no, that was the original issue that I was running into, which needed
> commit 241b2719 - prior to that commit, if the conn was already UP,
> we'd end up doing a rds_conn_drop on a good connection, and both sides
> would end up in a pair of infinite 3WH loops. Even if we dont do
> a rds_conn_drop on the UP connection, we've just (before
> rds_tcp_accept_one) sent out a syn-ack on the incoming syn, and now
> need to RST that syn-ac. The other side is going to receive the rst,
> and get confused about what to clean up (since there's already an UP
> connection going on).
>
> In short, when there is a duel, it's cleanest to have a deterministic
> arbitration- both sides use the numeric value of saddr and faddr to
> figure out which side is active, which side is passive. (Thus the
> basis on the BGP router-id based model for 241b2719)
>
> FWIW, much of this is actually a corner case- in practice, its not
> frequent to have syns crossing each other at "almost the same time".
>
Sounds good. Thanks for expanding it. Patch looks good to me.
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
^ permalink raw reply
* Re: [PATCH net 2/2] RDS: TCP: Synchrnozize accept() and connect() paths on t_conn_lock.
From: Santosh Shilimkar @ 2016-05-02 18:08 UTC (permalink / raw)
To: Sowmini Varadhan; +Cc: netdev, rds-devel, davem
In-Reply-To: <20160502164307.GE20517@oracle.com>
On 5/2/2016 9:43 AM, Sowmini Varadhan wrote:
> On (05/02/16 09:33), Santosh Shilimkar wrote:
>>> + mutex_unlock(&tc->t_conn_lock);
>> Just wondering whether the spin_lock() would better here considering
>> entry into rds_tcp_conn_connect() & rds_tcp_accept_one() might be
>> from softirq context. Ignore it if its not applicable.
>
> It's not from softirq context (both are workqs), but I used a mutex
> to follow c_cm_lock (which I considered reusing, given that it
> is only IB specific?) But spin_lock vs mutex may not be a big
> differentiator here- this is really a one-time start up (corner-case)
> issue in the control path.
>
That should be fine then.
>>> rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING);
>> Like patch 1/2, probably we can leverage return value of above.
> :
>> You probably don't need the local 'conn_state' and below should work.
>> if (!rds_conn_connecting(conn) && !rds_conn_up(conn))
>
> see explanation for comment to 1/2.
>
Yep.
> +rst_nsk:
> + /* rest the newly returned accept sock and bail */
s/rest/reset
With typo fixed,
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
^ permalink raw reply
* [PATCH net v2 1/2] RDS:TCP: Synchronize rds_tcp_accept_one with rds_send_xmit when resetting t_sock
From: Sowmini Varadhan @ 2016-05-02 18:24 UTC (permalink / raw)
To: sowmini.varadhan, netdev, rds-devel; +Cc: santosh.shilimkar, davem
In-Reply-To: <cover.1462212462.git.sowmini.varadhan@oracle.com>
There is a race condition between rds_send_xmit -> rds_tcp_xmit
and the code that deals with resolution of duelling syns added
by commit 241b271952eb ("RDS-TCP: Reset tcp callbacks if re-using an
outgoing socket in rds_tcp_accept_one()").
Specifically, we may end up derefencing a null pointer in rds_send_xmit
if we have the interleaving sequence:
rds_tcp_accept_one rds_send_xmit
conn is RDS_CONN_UP, so
invoke rds_tcp_xmit
tc = conn->c_transport_data
rds_tcp_restore_callbacks
/* reset t_sock */
null ptr deref from tc->t_sock
The race condition can be avoided without adding the overhead of
additional locking in the xmit path: have rds_tcp_accept_one wait
for rds_tcp_xmit threads to complete before resetting callbacks.
The synchronization can be done in the same manner as rds_conn_shutdown().
First set the rds_conn_state to something other than RDS_CONN_UP
(so that new threads cannot get into rds_tcp_xmit()), then wait for
RDS_IN_XMIT to be cleared in the conn->c_flags indicating that any
threads in rds_tcp_xmit are done.
Fixes: 241b271952eb ("RDS-TCP: Reset tcp callbacks if re-using an
outgoing socket in rds_tcp_accept_one()")
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
---
v2: spelling edit in commit: s/sequencee/sequence
net/rds/tcp.c | 2 +-
net/rds/tcp_listen.c | 40 ++++++++++++++++++++++++----------------
2 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 61ed2a8..9134544 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -127,7 +127,7 @@ void rds_tcp_restore_callbacks(struct socket *sock,
/*
* This is the only path that sets tc->t_sock. Send and receive trust that
- * it is set. The RDS_CONN_CONNECTED bit protects those paths from being
+ * it is set. The RDS_CONN_UP bit protects those paths from being
* called while it isn't set.
*/
void rds_tcp_set_callbacks(struct socket *sock, struct rds_connection *conn)
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c
index 0936a4a..0896187 100644
--- a/net/rds/tcp_listen.c
+++ b/net/rds/tcp_listen.c
@@ -115,24 +115,32 @@ int rds_tcp_accept_one(struct socket *sock)
* rds_tcp_state_change() will do that cleanup
*/
rs_tcp = (struct rds_tcp_connection *)conn->c_transport_data;
- if (rs_tcp->t_sock &&
- ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr)) {
- struct sock *nsk = new_sock->sk;
-
- nsk->sk_user_data = NULL;
- nsk->sk_prot->disconnect(nsk, 0);
- tcp_done(nsk);
- new_sock = NULL;
- ret = 0;
- goto out;
- } else if (rs_tcp->t_sock) {
- rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp);
- conn->c_outgoing = 0;
- }
-
rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING);
+ if (rs_tcp->t_sock) {
+ /* Need to resolve a duelling SYN between peers.
+ * We have an outstanding SYN to this peer, which may
+ * potentially have transitioned to the RDS_CONN_UP state,
+ * so we must quiesce any send threads before resetting
+ * c_transport_data.
+ */
+ wait_event(conn->c_waitq,
+ !test_bit(RDS_IN_XMIT, &conn->c_flags));
+ if (ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr)) {
+ struct sock *nsk = new_sock->sk;
+
+ nsk->sk_user_data = NULL;
+ nsk->sk_prot->disconnect(nsk, 0);
+ tcp_done(nsk);
+ new_sock = NULL;
+ ret = 0;
+ goto out;
+ } else if (rs_tcp->t_sock) {
+ rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp);
+ conn->c_outgoing = 0;
+ }
+ }
rds_tcp_set_callbacks(new_sock, conn);
- rds_connect_complete(conn);
+ rds_connect_complete(conn); /* marks RDS_CONN_UP */
new_sock = NULL;
ret = 0;
--
1.7.1
^ permalink raw reply related
* [PATCH net v2 2/2] RDS: TCP: Synchronize accept() and connect() paths on t_conn_lock.
From: Sowmini Varadhan @ 2016-05-02 18:24 UTC (permalink / raw)
To: sowmini.varadhan, netdev, rds-devel; +Cc: santosh.shilimkar, davem
In-Reply-To: <cover.1462212462.git.sowmini.varadhan@oracle.com>
An arbitration scheme for duelling SYNs is implemented as part of
commit 241b271952eb ("RDS-TCP: Reset tcp callbacks if re-using an
outgoing socket in rds_tcp_accept_one()") which ensures that both nodes
involved will arrive at the same arbitration decision. However, this
needs to be synchronized with an outgoing SYN to be generated by
rds_tcp_conn_connect(). This commit achieves the synchronization
through the t_conn_lock mutex in struct rds_tcp_connection.
The rds_conn_state is checked in rds_tcp_conn_connect() after acquiring
the t_conn_lock mutex. A SYN is sent out only if the RDS connection is
not already UP (an UP would indicate that rds_tcp_accept_one() has
completed 3WH, so no SYN needs to be generated).
Similarly, the rds_conn_state is checked in rds_tcp_accept_one() after
acquiring the t_conn_lock mutex. The only acceptable states (to
allow continuation of the arbitration logic) are UP (i.e., outgoing SYN
was SYN-ACKed by peer after it sent us the SYN) or CONNECTING (we sent
outgoing SYN before we saw incoming SYN).
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
---
v2: review comments from Santosh Shilimkar
net/rds/tcp.c | 1 +
net/rds/tcp.h | 4 ++++
net/rds/tcp_connect.c | 8 ++++++++
net/rds/tcp_listen.c | 30 ++++++++++++++++++++----------
4 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 9134544..86187da 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -216,6 +216,7 @@ static int rds_tcp_conn_alloc(struct rds_connection *conn, gfp_t gfp)
if (!tc)
return -ENOMEM;
+ mutex_init(&tc->t_conn_lock);
tc->t_sock = NULL;
tc->t_tinc = NULL;
tc->t_tinc_hdr_rem = sizeof(struct rds_header);
diff --git a/net/rds/tcp.h b/net/rds/tcp.h
index 64f873c..41c2283 100644
--- a/net/rds/tcp.h
+++ b/net/rds/tcp.h
@@ -12,6 +12,10 @@ struct rds_tcp_connection {
struct list_head t_tcp_node;
struct rds_connection *conn;
+ /* t_conn_lock synchronizes the connection establishment between
+ * rds_tcp_accept_one and rds_tcp_conn_connect
+ */
+ struct mutex t_conn_lock;
struct socket *t_sock;
void *t_orig_write_space;
void *t_orig_data_ready;
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c
index 5cb1687..49a3fcf 100644
--- a/net/rds/tcp_connect.c
+++ b/net/rds/tcp_connect.c
@@ -78,7 +78,14 @@ int rds_tcp_conn_connect(struct rds_connection *conn)
struct socket *sock = NULL;
struct sockaddr_in src, dest;
int ret;
+ struct rds_tcp_connection *tc = conn->c_transport_data;
+
+ mutex_lock(&tc->t_conn_lock);
+ if (rds_conn_up(conn)) {
+ mutex_unlock(&tc->t_conn_lock);
+ return 0;
+ }
ret = sock_create_kern(rds_conn_net(conn), PF_INET,
SOCK_STREAM, IPPROTO_TCP, &sock);
if (ret < 0)
@@ -120,6 +127,7 @@ int rds_tcp_conn_connect(struct rds_connection *conn)
}
out:
+ mutex_unlock(&tc->t_conn_lock);
if (sock)
sock_release(sock);
return ret;
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c
index 0896187..be263cd 100644
--- a/net/rds/tcp_listen.c
+++ b/net/rds/tcp_listen.c
@@ -76,7 +76,9 @@ int rds_tcp_accept_one(struct socket *sock)
struct rds_connection *conn;
int ret;
struct inet_sock *inet;
- struct rds_tcp_connection *rs_tcp;
+ struct rds_tcp_connection *rs_tcp = NULL;
+ int conn_state;
+ struct sock *nsk;
ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family,
sock->sk->sk_type, sock->sk->sk_protocol,
@@ -116,6 +118,10 @@ int rds_tcp_accept_one(struct socket *sock)
*/
rs_tcp = (struct rds_tcp_connection *)conn->c_transport_data;
rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING);
+ mutex_lock(&rs_tcp->t_conn_lock);
+ conn_state = rds_conn_state(conn);
+ if (conn_state != RDS_CONN_CONNECTING && conn_state != RDS_CONN_UP)
+ goto rst_nsk;
if (rs_tcp->t_sock) {
/* Need to resolve a duelling SYN between peers.
* We have an outstanding SYN to this peer, which may
@@ -126,14 +132,7 @@ int rds_tcp_accept_one(struct socket *sock)
wait_event(conn->c_waitq,
!test_bit(RDS_IN_XMIT, &conn->c_flags));
if (ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr)) {
- struct sock *nsk = new_sock->sk;
-
- nsk->sk_user_data = NULL;
- nsk->sk_prot->disconnect(nsk, 0);
- tcp_done(nsk);
- new_sock = NULL;
- ret = 0;
- goto out;
+ goto rst_nsk;
} else if (rs_tcp->t_sock) {
rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp);
conn->c_outgoing = 0;
@@ -143,8 +142,19 @@ int rds_tcp_accept_one(struct socket *sock)
rds_connect_complete(conn); /* marks RDS_CONN_UP */
new_sock = NULL;
ret = 0;
-
+ goto out;
+rst_nsk:
+ /* reset the newly returned accept sock and bail */
+ nsk = new_sock->sk;
+ rds_tcp_stats_inc(s_tcp_listen_closed_stale);
+ nsk->sk_user_data = NULL;
+ nsk->sk_prot->disconnect(nsk, 0);
+ tcp_done(nsk);
+ new_sock = NULL;
+ ret = 0;
out:
+ if (rs_tcp)
+ mutex_unlock(&rs_tcp->t_conn_lock);
if (new_sock)
sock_release(new_sock);
return ret;
--
1.7.1
^ permalink raw reply related
* [PATCH net v2 0/2] RDS: TCP: sychronization during connection startup
From: Sowmini Varadhan @ 2016-05-02 18:24 UTC (permalink / raw)
To: sowmini.varadhan, netdev, rds-devel; +Cc: santosh.shilimkar, davem
This patch series ensures that the passive (accept) side of the
TCP connection used for RDS-TCP is correctly synchronized with
any concurrent active (connect) attempts for a given pair of peers.
Patch 1 in the series makes sure that the t_sock in struct
rds_tcp_connection is only reset after any threads in rds_tcp_xmit
have completed (otherwise a null-ptr deref may be encountered).
Patch 2 synchronizes rds_tcp_accept_one() with the rds_tcp*connect()
path.
v2: review comments from Santosh Shilimkar, other spelling corrections
Sowmini Varadhan (2):
RDS:TCP: Synchronize rds_tcp_accept_one with rds_send_xmit when
resetting t_sock
RDS: TCP: Synchronize accept() and connect() paths on t_conn_lock.
net/rds/tcp.c | 3 +-
net/rds/tcp.h | 4 +++
net/rds/tcp_connect.c | 8 +++++++
net/rds/tcp_listen.c | 54 ++++++++++++++++++++++++++++++++----------------
4 files changed, 50 insertions(+), 19 deletions(-)
^ permalink raw reply
* Re: [PATCH v2] net: macb: do not scan PHYs manually
From: Josh Cartwright @ 2016-05-02 18:36 UTC (permalink / raw)
To: Nicolas Ferre
Cc: Andrew Lunn, Nathan Sullivan, netdev, linux-kernel,
Florian Fainelli, Alexandre Belloni
In-Reply-To: <57235655.3030104@atmel.com>
[-- Attachment #1: Type: text/plain, Size: 1941 bytes --]
On Fri, Apr 29, 2016 at 02:40:53PM +0200, Nicolas Ferre wrote:
[..]
> > static int macb_mii_init(struct macb *bp)
> > {
> > struct macb_platform_data *pdata;
> > struct device_node *np;
> > - int err = -ENXIO, i;
> > + int err = -ENXIO;
> >
> > /* Enable management port */
> > macb_writel(bp, NCR, MACB_BIT(MPE));
> > @@ -446,33 +497,10 @@ static int macb_mii_init(struct macb *bp)
> > dev_set_drvdata(&bp->dev->dev, bp->mii_bus);
> >
> > np = bp->pdev->dev.of_node;
> > - if (np) {
> > - /* try dt phy registration */
> > - err = of_mdiobus_register(bp->mii_bus, np);
> > -
> > - /* fallback to standard phy registration if no phy were
> > - * found during dt phy registration
> > - */
> > - if (!err && !phy_find_first(bp->mii_bus)) {
> > - for (i = 0; i < PHY_MAX_ADDR; i++) {
> > - struct phy_device *phydev;
> > -
> > - phydev = mdiobus_scan(bp->mii_bus, i);
> > - if (IS_ERR(phydev)) {
> > - err = PTR_ERR(phydev);
> > - break;
> > - }
> > - }
> > -
> > - if (err)
> > - goto err_out_unregister_bus;
> > - }
> > - } else {
> > - if (pdata)
> > - bp->mii_bus->phy_mask = pdata->phy_mask;
> > -
> > - err = mdiobus_register(bp->mii_bus);
> > - }
> > + if (np)
> > + err = macb_mii_of_init(bp, np);
> > + else
> > + err = macb_mii_pdata_init(bp, pdata);
> >
> > if (err)
> > goto err_out_free_mdiobus;
>
> I'm okay with this. Thanks for having taken the initiative to implement it.
Unfortunately, I don't think it's going to be as straightforward
as I originally thought. Still doable, but more complicated.
In particular, the macb bindings allow for a user to specify a
'reset-gpios' property _at the PHY_ level, which is consumed by the
macb to adjust the PHY reset state on remove.
My question is: why is the PHY reset GPIO management not the
responsibility of the PHY driver/core itself?
Josh
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply
* Re: [PATCHv2 bluetooth-next 01/10] 6lowpan: add private neighbour data
From: Hannes Frederic Sowa @ 2016-05-02 18:59 UTC (permalink / raw)
To: Alexander Aring, linux-wpan
Cc: kernel, marcel, jukka.rissanen, stefan, mcr, werner,
linux-bluetooth, netdev, David S . Miller
In-Reply-To: <1461140382-4784-2-git-send-email-aar@pengutronix.de>
Hello,
On 20.04.2016 10:19, Alexander Aring wrote:
> This patch will introduce a 6lowpan neighbour private data. Like the
> interface private data we handle private data for generic 6lowpan and
> for link-layer specific 6lowpan.
>
> The current first use case if to save the short address for a 802.15.4
> 6lowpan neighbour.
>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Alexander Aring <aar@pengutronix.de>
> ---
> include/linux/netdevice.h | 3 +--
> include/net/6lowpan.h | 24 ++++++++++++++++++++++++
> net/bluetooth/6lowpan.c | 2 ++
> net/ieee802154/6lowpan/core.c | 12 ++++++++++++
> 4 files changed, 39 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 166402a..0052c42 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -1487,8 +1487,7 @@ enum netdev_priv_flags {
> * @perm_addr: Permanent hw address
> * @addr_assign_type: Hw address assignment type
> * @addr_len: Hardware address length
> - * @neigh_priv_len; Used in neigh_alloc(),
> - * initialized only in atm/clip.c
> + * @neigh_priv_len; Used in neigh_alloc()
> * @dev_id: Used to differentiate devices that share
> * the same link layer address
> * @dev_port: Used to differentiate devices that share
> diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
> index da84cf9..61c6517 100644
> --- a/include/net/6lowpan.h
> +++ b/include/net/6lowpan.h
> @@ -98,6 +98,9 @@ static inline bool lowpan_is_iphc(u8 dispatch)
> #define LOWPAN_PRIV_SIZE(llpriv_size) \
> (sizeof(struct lowpan_dev) + llpriv_size)
>
> +#define LOWPAN_NEIGH_PRIV_SIZE(llneigh_priv_size) \
> + (sizeof(struct lowpan_neigh) + llneigh_priv_size)
> +
> enum lowpan_lltypes {
> LOWPAN_LLTYPE_BTLE,
> LOWPAN_LLTYPE_IEEE802154,
> @@ -141,6 +144,27 @@ struct lowpan_dev {
> u8 priv[0] __aligned(sizeof(void *));
> };
>
> +struct lowpan_neigh {
> + /* 6LoWPAN neigh private data */
> + /* must be last */
> + u8 priv[0] __aligned(sizeof(void *));
Are you sure this declaration is correct? You take its size above, which
should result in zero. Looks a little bit strange. :)
> +};
> +
> +struct lowpan_802154_neigh {
> + __le16 short_addr;
> +};
> +
> +static inline struct lowpan_neigh *lowpan_neigh(void *neigh_priv)
> +{
> + return neigh_priv;
> +}
> +
> +static inline
> +struct lowpan_802154_neigh *lowpan_802154_neigh(void *neigh_priv)
> +{
> + return (struct lowpan_802154_neigh *)lowpan_neigh(neigh_priv)->priv;
> +}
Can't you remove lowpan_neigh completely and just use 802154_neigh at
this point?
Bye,
Hannes
^ permalink raw reply
* Re: [PATCHv2 bluetooth-next 02/10] 6lowpan: add 802.15.4 short addr slaac
From: Hannes Frederic Sowa @ 2016-05-02 19:06 UTC (permalink / raw)
To: Alexander Aring, linux-wpan
Cc: kernel, marcel, jukka.rissanen, stefan, mcr, werner,
linux-bluetooth, netdev, David S . Miller, Alexey Kuznetsov,
James Morris, Hideaki YOSHIFUJI, Patrick McHardy
In-Reply-To: <1461140382-4784-3-git-send-email-aar@pengutronix.de>
On 20.04.2016 10:19, Alexander Aring wrote:
> This patch adds the autoconfiguration if a valid 802.15.4 short address
> is available for 802.15.4 6LoWPAN interfaces.
>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
> Cc: James Morris <jmorris@namei.org>
> Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
> Cc: Patrick McHardy <kaber@trash.net>
> Signed-off-by: Alexander Aring <aar@pengutronix.de>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Thanks,
Hannes
^ permalink raw reply
* Re: [PATCHv2 bluetooth-next 03/10] 6lowpan: remove ipv6 module request
From: Hannes Frederic Sowa @ 2016-05-02 19:06 UTC (permalink / raw)
To: Alexander Aring, linux-wpan
Cc: kernel, marcel, jukka.rissanen, stefan, mcr, werner,
linux-bluetooth, netdev
In-Reply-To: <1461140382-4784-4-git-send-email-aar@pengutronix.de>
On 20.04.2016 10:19, Alexander Aring wrote:
> Since we use exported function from ipv6 kernel module we don't need to
> request the module anymore to have ipv6 functionality.
>
> Signed-off-by: Alexander Aring <aar@pengutronix.de>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
^ permalink raw reply
* Re: [PATCH v2] net: macb: do not scan PHYs manually
From: Florian Fainelli @ 2016-05-02 19:08 UTC (permalink / raw)
To: Josh Cartwright, Nicolas Ferre
Cc: Andrew Lunn, Nathan Sullivan, netdev, linux-kernel,
Alexandre Belloni
In-Reply-To: <20160502183626.GC31001@jcartwri.amer.corp.natinst.com>
On 02/05/16 11:36, Josh Cartwright wrote:
> On Fri, Apr 29, 2016 at 02:40:53PM +0200, Nicolas Ferre wrote:
> [..]
>>> static int macb_mii_init(struct macb *bp)
>>> {
>>> struct macb_platform_data *pdata;
>>> struct device_node *np;
>>> - int err = -ENXIO, i;
>>> + int err = -ENXIO;
>>>
>>> /* Enable management port */
>>> macb_writel(bp, NCR, MACB_BIT(MPE));
>>> @@ -446,33 +497,10 @@ static int macb_mii_init(struct macb *bp)
>>> dev_set_drvdata(&bp->dev->dev, bp->mii_bus);
>>>
>>> np = bp->pdev->dev.of_node;
>>> - if (np) {
>>> - /* try dt phy registration */
>>> - err = of_mdiobus_register(bp->mii_bus, np);
>>> -
>>> - /* fallback to standard phy registration if no phy were
>>> - * found during dt phy registration
>>> - */
>>> - if (!err && !phy_find_first(bp->mii_bus)) {
>>> - for (i = 0; i < PHY_MAX_ADDR; i++) {
>>> - struct phy_device *phydev;
>>> -
>>> - phydev = mdiobus_scan(bp->mii_bus, i);
>>> - if (IS_ERR(phydev)) {
>>> - err = PTR_ERR(phydev);
>>> - break;
>>> - }
>>> - }
>>> -
>>> - if (err)
>>> - goto err_out_unregister_bus;
>>> - }
>>> - } else {
>>> - if (pdata)
>>> - bp->mii_bus->phy_mask = pdata->phy_mask;
>>> -
>>> - err = mdiobus_register(bp->mii_bus);
>>> - }
>>> + if (np)
>>> + err = macb_mii_of_init(bp, np);
>>> + else
>>> + err = macb_mii_pdata_init(bp, pdata);
>>>
>>> if (err)
>>> goto err_out_free_mdiobus;
>>
>> I'm okay with this. Thanks for having taken the initiative to implement it.
>
> Unfortunately, I don't think it's going to be as straightforward
> as I originally thought. Still doable, but more complicated.
>
> In particular, the macb bindings allow for a user to specify a
> 'reset-gpios' property _at the PHY_ level, which is consumed by the
> macb to adjust the PHY reset state on remove.
In fact, not just on remove, anytime there is an opportunity to save
power (interface down, closed) and putting the PHY into reset is usually
guaranteed to be saving more power than e.g: a BMCR power down.
>
> My question is: why is the PHY reset GPIO management not the
> responsibility of the PHY driver/core itself?
Well, this is actually being worked on at the moment by Sergei, since
there is not necessarily a reason why PHYLIB can't deal with that:
https://lkml.org/lkml/2016/4/28/831
--
Florian
^ permalink raw reply
* Re: [PATCH net-next 1/2] net: SOCKWQ_ASYNC_NOSPACE optimizations
From: Jiri Pirko @ 2016-05-02 19:12 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Eric Dumazet, David S . Miller, netdev, eladr, idosch
In-Reply-To: <1462206138.5535.255.camel@edumazet-glaptop3.roam.corp.google.com>
Mon, May 02, 2016 at 06:22:18PM CEST, eric.dumazet@gmail.com wrote:
>On Mon, 2016-05-02 at 18:16 +0200, Jiri Pirko wrote:
>> Mon, Apr 25, 2016 at 07:39:32PM CEST, edumazet@google.com wrote:
>> >SOCKWQ_ASYNC_NOSPACE is tested in sock_wake_async()
>> >so that a SIGIO signal is sent when needed.
>> >
>> >tcp_sendmsg() clears the bit.
>> >tcp_poll() sets the bit when stream is not writeable.
>> >
>> >We can avoid two atomic operations by first checking if socket
>> >is actually interested in the FASYNC business (most sockets in
>> >real applications do not use AIO, but select()/poll()/epoll())
>> >
>> >This also removes one cache line miss to access sk->sk_wq->flags
>> >in tcp_sendmsg()
>> >
>> >Signed-off-by: Eric Dumazet <edumazet@google.com>
>>
>> I just bisected down to this. This is causing a regression for me when
>> my nfs mount becomes stuck. I can easily reproduce this if you need to
>> test the fix.
>
>What do you mean by 'when nfs mount becomes stuck' ?
>
>Is this patch making nfs not functional , or does it make recovery from
>some nfs error bad ?
I can mount nfs on the host. But when I do something (compile a kernel
module in my case), it gets stuck. Then I cannot even ssh to the machine.
No messages in dmesg. I didn't debug it any further. I just bisected and
verified that this patch caused this behaviour.
^ permalink raw reply
* Re: [PATCH next-next 0/7] net: Cleanup IPv6 ip tunnels
From: Tom Herbert @ 2016-05-02 19:32 UTC (permalink / raw)
To: Alexander Duyck; +Cc: David Miller, Netdev, Kernel Team
In-Reply-To: <CAKgT0UfwyZW7kifpU18xtwT77=Zex3AzJp=xry=siW1NVCyX+A@mail.gmail.com>
On Fri, Apr 29, 2016 at 6:00 PM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Fri, Apr 29, 2016 at 5:12 PM, Tom Herbert <tom@herbertland.com> wrote:
>> The IPv6 tunnel code is very different from IPv4 code. There is a lot
>> of redundancy with the IPv4 code, particularly in the GRE tunneling.
>>
>> This patch set cleans up the tunnel code to make the IPv6 code look
>> more like the IPv4 code and use common functions between the two
>> stacks where possible.
>>
>> This work should make it easier to maintain and extend the IPv6 ip
>> tunnels.
>>
>> Items in this patch set:
>> - Cleanup IPv6 tunnel receive path (ip6_tnl_rcv). Includes using
>> gro_cells and exporting ip6_tnl_rcv so the ip6_gre can call it
>> - Move GRE functions to common header file (tx functions) or
>> gre_demux.c (rx functions like gre_parse_header)
>> - Call common GRE functions from IPv6 GRE
>> - Create ip6_tnl_xmit (to be like ip_tunnel_xmit)
>>
>> Tested:
>> Ran super_netperf tests for TCP_RR and TCP_STREAM for:
>> - IPv4 over gre, gretap, gre6, gre6tap
>> - IPv6 over gre, gretap, gre6, gre6tap
>> - ipip
>> - ip6ip6
>> - ipip/gue
>> - IPv6 over gre/gue
>> - IPv4 over gre/gue
>
> You should probably add 2 additional test cases. One for IPv4 GRE/GUE
> w/ checksum on the GRE header, and same for IPv6. It was broken
> previously in terms of offloads so we need to make sure we don't
> introduce a regression and break it again.
>
Hi Alexander,
I did test GRE/GUE with checksum and remcsum for IPv4, that works okay.
Support for GUE with IPv6 is in the next patch set I am working on.
Thanks,
Tom
>> Tom Herbert (7):
>> ipv6: Cleanup IPv6 tunnel receive path
>> gre: Move utility functions to common headers
>> gre6: Cleanup GREv6 receive path, call common GRE functions
>> ipv6: Create ip6_tnl_xmit
>> gre: Create common functions for transmit
>> ipv6: Generic tunnel cleanup
>> gre6: Cleanup GREv6 transmit path, call common GRE functions
>>
>> include/net/gre.h | 104 +++++++++++++
>> include/net/ip6_tunnel.h | 11 +-
>> net/ipv4/gre_demux.c | 64 ++++++++
>> net/ipv4/ip_gre.c | 199 +++---------------------
>> net/ipv6/ip6_gre.c | 392 +++++++++--------------------------------------
>> net/ipv6/ip6_tunnel.c | 266 +++++++++++++++++++++-----------
>> 6 files changed, 452 insertions(+), 584 deletions(-)
>>
>> --
>> 2.8.0.rc2
>>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox