From patchwork Sat Jul 20 10:13:52 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 260430 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 978132C007B for ; Sat, 20 Jul 2013 20:14:22 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753649Ab3GTKOP (ORCPT ); Sat, 20 Jul 2013 06:14:15 -0400 Received: from mail-ee0-f54.google.com ([74.125.83.54]:60936 "EHLO mail-ee0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753408Ab3GTKOD (ORCPT ); Sat, 20 Jul 2013 06:14:03 -0400 Received: by mail-ee0-f54.google.com with SMTP id t10so2847746eei.13 for ; Sat, 20 Jul 2013 03:14:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=G1f+cBQMNBtD4lXU2G81Bo0vpFR2JERGwNnIZkl7ItQ=; b=Jig+/uU0ISF36U7b9CIBbq8mMNk/NY85o0KJogpfWRIb76Lf7Yk8TnE+NvK9ukYJ8U hMpYcT+V6vDkhZ2teRMh02/yqr2x97Z1EDfm8H3+WHWGbyo/6LSIsMZUpzBWk1M17Upu KQgnP3TETP6mMLXvs3qUoSIDAJQWpXPSTQ0NfG3gHnGL12D+E5twF5vLZYa1DroO5RFD Jih7kaAAPOPp2wiHUkox+m8BCGl53MR97foo33Qe2gcXbmI9hYCMJ7zpjhBSg+CKQiNr sQkOGQfgF8pZv6hm6P1UjWEcmyqcKCz2iOakJmra8V+/keCzkd1KbcDvlruYd9aV1N3X Q/1Q== X-Received: by 10.14.87.4 with SMTP id x4mr19368278eee.121.1374315241579; Sat, 20 Jul 2013 03:14:01 -0700 (PDT) Received: from localhost (sun-0.pirko.cz. [84.16.102.25]) by mx.google.com with ESMTPSA id i2sm34212118eeu.4.2013.07.20.03.13.59 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 20 Jul 2013 03:14:00 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org Cc: davem@davemloft.net, fubar@us.ibm.com, andy@greyhouse.net, kaber@trash.net, stephen@networkplumber.org, kuznet@ms2.inr.ac.ru, jmorris@namei.org, yoshfuji@linux-ipv6.org, edumazet@google.com Subject: [patch net-next v2 1/3] team: add peer notification Date: Sat, 20 Jul 2013 12:13:52 +0200 Message-Id: <1374315234-7096-2-git-send-email-jiri@resnulli.us> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1374315234-7096-1-git-send-email-jiri@resnulli.us> References: <1374315234-7096-1-git-send-email-jiri@resnulli.us> X-Gm-Message-State: ALoCoQlghV6kez70GLtjbnrxeD9DB+6HUEipMVNVgbOHC16yS9jPMuc2c9rQLHDTOKPHInhzB+wj Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org When port is enabled or disabled, allow to notify peers by unsolicitated NAs or gratuitous ARPs. Disabled by default. Signed-off-by: Jiri Pirko --- drivers/net/team/team.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/if_team.h | 8 ++++- 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index bff7e0b..0433ee9 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -622,6 +622,46 @@ static int team_change_mode(struct team *team, const char *kind) } +/********************* + * Peers notification + *********************/ + +static void team_notify_peers_work(struct work_struct *work) +{ + struct team *team; + + team = container_of(work, struct team, notify_peers.dw.work); + + if (!rtnl_trylock()) { + schedule_delayed_work(&team->notify_peers.dw, 0); + return; + } + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, team->dev); + rtnl_unlock(); + if (!atomic_dec_and_test(&team->notify_peers.count_pending)) + schedule_delayed_work(&team->notify_peers.dw, + msecs_to_jiffies(team->notify_peers.interval)); +} + +static void team_notify_peers(struct team *team) +{ + if (!team->notify_peers.count || !netif_running(team->dev)) + return; + atomic_set(&team->notify_peers.count_pending, team->notify_peers.count); + schedule_delayed_work(&team->notify_peers.dw, 0); +} + +static void team_notify_peers_init(struct team *team) +{ + INIT_DELAYED_WORK(&team->notify_peers.dw, team_notify_peers_work); +} + +static void team_notify_peers_fini(struct team *team) +{ + cancel_delayed_work_sync(&team->notify_peers.dw); +} + + /************************ * Rx path frame handler ************************/ @@ -846,6 +886,7 @@ static void team_port_enable(struct team *team, team_queue_override_port_add(team, port); if (team->ops.port_enabled) team->ops.port_enabled(team, port); + team_notify_peers(team); } static void __reconstruct_port_hlist(struct team *team, int rm_index) @@ -875,6 +916,7 @@ static void team_port_disable(struct team *team, team->en_port_count--; team_queue_override_port_del(team, port); team_adjust_ops(team); + team_notify_peers(team); } #define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ @@ -1205,6 +1247,34 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) return team_change_mode(team, ctx->data.str_val); } +static int team_notify_peers_count_get(struct team *team, + struct team_gsetter_ctx *ctx) +{ + ctx->data.u32_val = team->notify_peers.count; + return 0; +} + +static int team_notify_peers_count_set(struct team *team, + struct team_gsetter_ctx *ctx) +{ + team->notify_peers.count = ctx->data.u32_val; + return 0; +} + +static int team_notify_peers_interval_get(struct team *team, + struct team_gsetter_ctx *ctx) +{ + ctx->data.u32_val = team->notify_peers.interval; + return 0; +} + +static int team_notify_peers_interval_set(struct team *team, + struct team_gsetter_ctx *ctx) +{ + team->notify_peers.interval = ctx->data.u32_val; + return 0; +} + static int team_port_en_option_get(struct team *team, struct team_gsetter_ctx *ctx) { @@ -1317,6 +1387,18 @@ static const struct team_option team_options[] = { .setter = team_mode_option_set, }, { + .name = "notify_peers_count", + .type = TEAM_OPTION_TYPE_U32, + .getter = team_notify_peers_count_get, + .setter = team_notify_peers_count_set, + }, + { + .name = "notify_peers_interval", + .type = TEAM_OPTION_TYPE_U32, + .getter = team_notify_peers_interval_get, + .setter = team_notify_peers_interval_set, + }, + { .name = "enabled", .type = TEAM_OPTION_TYPE_BOOL, .per_port = true, @@ -1396,6 +1478,9 @@ static int team_init(struct net_device *dev) INIT_LIST_HEAD(&team->option_list); INIT_LIST_HEAD(&team->option_inst_list); + + team_notify_peers_init(team); + err = team_options_register(team, team_options, ARRAY_SIZE(team_options)); if (err) goto err_options_register; @@ -1406,6 +1491,7 @@ static int team_init(struct net_device *dev) return 0; err_options_register: + team_notify_peers_fini(team); team_queue_override_fini(team); err_team_queue_override_init: free_percpu(team->pcpu_stats); @@ -1425,6 +1511,7 @@ static void team_uninit(struct net_device *dev) __team_change_mode(team, NULL); /* cleanup */ __team_options_unregister(team, team_options, ARRAY_SIZE(team_options)); + team_notify_peers_fini(team); team_queue_override_fini(team); mutex_unlock(&team->lock); } diff --git a/include/linux/if_team.h b/include/linux/if_team.h index f6156f9..b0b8368 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -10,9 +10,9 @@ #ifndef _LINUX_IF_TEAM_H_ #define _LINUX_IF_TEAM_H_ - #include #include +#include #include struct team_pcpu_stats { @@ -194,6 +194,12 @@ struct team { bool user_carrier_enabled; bool queue_override_enabled; struct list_head *qom_lists; /* array of queue override mapping lists */ + struct { + unsigned int count; + unsigned int interval; /* in ms */ + atomic_t count_pending; + struct delayed_work dw; + } notify_peers; long mode_priv[TEAM_MODE_PRIV_LONGS]; };