Commit 80f7c668 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller

team: add support for per-port options

This patch allows to create per-port options. That becomes handy for all
sorts of stuff, for example for userspace driven link-state, 802.3ad
implementation and so on.
Signed-off-by: default avatarJiri Pirko <jpirko@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7a5cc242
This diff is collapsed.
...@@ -59,23 +59,21 @@ static void ab_port_leave(struct team *team, struct team_port *port) ...@@ -59,23 +59,21 @@ static void ab_port_leave(struct team *team, struct team_port *port)
RCU_INIT_POINTER(ab_priv(team)->active_port, NULL); RCU_INIT_POINTER(ab_priv(team)->active_port, NULL);
} }
static int ab_active_port_get(struct team *team, void *arg) static int ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx)
{ {
u32 *ifindex = arg;
*ifindex = 0;
if (ab_priv(team)->active_port) if (ab_priv(team)->active_port)
*ifindex = ab_priv(team)->active_port->dev->ifindex; ctx->data.u32_val = ab_priv(team)->active_port->dev->ifindex;
else
ctx->data.u32_val = 0;
return 0; return 0;
} }
static int ab_active_port_set(struct team *team, void *arg) static int ab_active_port_set(struct team *team, struct team_gsetter_ctx *ctx)
{ {
u32 *ifindex = arg;
struct team_port *port; struct team_port *port;
list_for_each_entry_rcu(port, &team->port_list, list) { list_for_each_entry_rcu(port, &team->port_list, list) {
if (port->dev->ifindex == *ifindex) { if (port->dev->ifindex == ctx->data.u32_val) {
rcu_assign_pointer(ab_priv(team)->active_port, port); rcu_assign_pointer(ab_priv(team)->active_port, port);
return 0; return 0;
} }
......
...@@ -52,22 +52,21 @@ static bool lb_transmit(struct team *team, struct sk_buff *skb) ...@@ -52,22 +52,21 @@ static bool lb_transmit(struct team *team, struct sk_buff *skb)
return false; return false;
} }
static int lb_bpf_func_get(struct team *team, void *arg) static int lb_bpf_func_get(struct team *team, struct team_gsetter_ctx *ctx)
{ {
struct team_option_binary *tbinary = team_optarg_tbinary(arg); if (!lb_priv(team)->orig_fprog) {
ctx->data.bin_val.len = 0;
memset(tbinary, 0, sizeof(*tbinary)); ctx->data.bin_val.ptr = NULL;
if (!lb_priv(team)->orig_fprog)
return 0; return 0;
}
tbinary->data_len = lb_priv(team)->orig_fprog->len * ctx->data.bin_val.len = lb_priv(team)->orig_fprog->len *
sizeof(struct sock_filter); sizeof(struct sock_filter);
tbinary->data = lb_priv(team)->orig_fprog->filter; ctx->data.bin_val.ptr = lb_priv(team)->orig_fprog->filter;
return 0; return 0;
} }
static int __fprog_create(struct sock_fprog **pfprog, u32 data_len, static int __fprog_create(struct sock_fprog **pfprog, u32 data_len,
void *data) const void *data)
{ {
struct sock_fprog *fprog; struct sock_fprog *fprog;
struct sock_filter *filter = (struct sock_filter *) data; struct sock_filter *filter = (struct sock_filter *) data;
...@@ -93,16 +92,15 @@ static void __fprog_destroy(struct sock_fprog *fprog) ...@@ -93,16 +92,15 @@ static void __fprog_destroy(struct sock_fprog *fprog)
kfree(fprog); kfree(fprog);
} }
static int lb_bpf_func_set(struct team *team, void *arg) static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
{ {
struct team_option_binary *tbinary = team_optarg_tbinary(arg);
struct sk_filter *fp = NULL; struct sk_filter *fp = NULL;
struct sock_fprog *fprog = NULL; struct sock_fprog *fprog = NULL;
int err; int err;
if (tbinary->data_len) { if (ctx->data.bin_val.len) {
err = __fprog_create(&fprog, tbinary->data_len, err = __fprog_create(&fprog, ctx->data.bin_val.len,
tbinary->data); ctx->data.bin_val.ptr);
if (err) if (err)
return err; return err;
err = sk_unattached_filter_create(&fp, fprog); err = sk_unattached_filter_create(&fp, fprog);
......
...@@ -71,25 +71,27 @@ enum team_option_type { ...@@ -71,25 +71,27 @@ enum team_option_type {
TEAM_OPTION_TYPE_BINARY, TEAM_OPTION_TYPE_BINARY,
}; };
struct team_gsetter_ctx {
union {
u32 u32_val;
const char *str_val;
struct {
const void *ptr;
u32 len;
} bin_val;
} data;
struct team_port *port;
};
struct team_option { struct team_option {
struct list_head list; struct list_head list;
const char *name; const char *name;
bool per_port;
enum team_option_type type; enum team_option_type type;
int (*getter)(struct team *team, void *arg); int (*getter)(struct team *team, struct team_gsetter_ctx *ctx);
int (*setter)(struct team *team, void *arg); int (*setter)(struct team *team, struct team_gsetter_ctx *ctx);
/* Custom gennetlink interface related flags */
bool changed;
bool removed;
}; };
struct team_option_binary {
u32 data_len;
void *data;
};
#define team_optarg_tbinary(arg) (*((struct team_option_binary **) arg))
struct team_mode { struct team_mode {
struct list_head list; struct list_head list;
const char *kind; const char *kind;
...@@ -118,6 +120,7 @@ struct team { ...@@ -118,6 +120,7 @@ struct team {
struct list_head port_list; struct list_head port_list;
struct list_head option_list; struct list_head option_list;
struct list_head option_inst_list; /* list of option instances */
const struct team_mode *mode; const struct team_mode *mode;
struct team_mode_ops ops; struct team_mode_ops ops;
...@@ -224,6 +227,7 @@ enum { ...@@ -224,6 +227,7 @@ enum {
TEAM_ATTR_OPTION_TYPE, /* u8 */ TEAM_ATTR_OPTION_TYPE, /* u8 */
TEAM_ATTR_OPTION_DATA, /* dynamic */ TEAM_ATTR_OPTION_DATA, /* dynamic */
TEAM_ATTR_OPTION_REMOVED, /* flag */ TEAM_ATTR_OPTION_REMOVED, /* flag */
TEAM_ATTR_OPTION_PORT_IFINDEX, /* u32 */ /* for per-port options */
__TEAM_ATTR_OPTION_MAX, __TEAM_ATTR_OPTION_MAX,
TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment