You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
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: Jiri Pirko <jpirko@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
7a5cc24277
commit
80f7c6683f
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
*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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -52,22 +52,21 @@ drop:
|
||||
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);
|
||||
|
||||
memset(tbinary, 0, sizeof(*tbinary));
|
||||
if (!lb_priv(team)->orig_fprog)
|
||||
if (!lb_priv(team)->orig_fprog) {
|
||||
ctx->data.bin_val.len = 0;
|
||||
ctx->data.bin_val.ptr = NULL;
|
||||
return 0;
|
||||
|
||||
tbinary->data_len = lb_priv(team)->orig_fprog->len *
|
||||
sizeof(struct sock_filter);
|
||||
tbinary->data = lb_priv(team)->orig_fprog->filter;
|
||||
}
|
||||
ctx->data.bin_val.len = lb_priv(team)->orig_fprog->len *
|
||||
sizeof(struct sock_filter);
|
||||
ctx->data.bin_val.ptr = lb_priv(team)->orig_fprog->filter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __fprog_create(struct sock_fprog **pfprog, u32 data_len,
|
||||
void *data)
|
||||
const void *data)
|
||||
{
|
||||
struct sock_fprog *fprog;
|
||||
struct sock_filter *filter = (struct sock_filter *) data;
|
||||
@@ -93,16 +92,15 @@ static void __fprog_destroy(struct sock_fprog *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 sock_fprog *fprog = NULL;
|
||||
int err;
|
||||
|
||||
if (tbinary->data_len) {
|
||||
err = __fprog_create(&fprog, tbinary->data_len,
|
||||
tbinary->data);
|
||||
if (ctx->data.bin_val.len) {
|
||||
err = __fprog_create(&fprog, ctx->data.bin_val.len,
|
||||
ctx->data.bin_val.ptr);
|
||||
if (err)
|
||||
return err;
|
||||
err = sk_unattached_filter_create(&fp, fprog);
|
||||
|
||||
@@ -71,25 +71,27 @@ enum team_option_type {
|
||||
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 list_head list;
|
||||
const char *name;
|
||||
bool per_port;
|
||||
enum team_option_type type;
|
||||
int (*getter)(struct team *team, void *arg);
|
||||
int (*setter)(struct team *team, void *arg);
|
||||
|
||||
/* Custom gennetlink interface related flags */
|
||||
bool changed;
|
||||
bool removed;
|
||||
int (*getter)(struct team *team, struct team_gsetter_ctx *ctx);
|
||||
int (*setter)(struct team *team, struct team_gsetter_ctx *ctx);
|
||||
};
|
||||
|
||||
struct team_option_binary {
|
||||
u32 data_len;
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define team_optarg_tbinary(arg) (*((struct team_option_binary **) arg))
|
||||
|
||||
struct team_mode {
|
||||
struct list_head list;
|
||||
const char *kind;
|
||||
@@ -118,6 +120,7 @@ struct team {
|
||||
struct list_head port_list;
|
||||
|
||||
struct list_head option_list;
|
||||
struct list_head option_inst_list; /* list of option instances */
|
||||
|
||||
const struct team_mode *mode;
|
||||
struct team_mode_ops ops;
|
||||
@@ -224,6 +227,7 @@ enum {
|
||||
TEAM_ATTR_OPTION_TYPE, /* u8 */
|
||||
TEAM_ATTR_OPTION_DATA, /* dynamic */
|
||||
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 - 1,
|
||||
|
||||
Reference in New Issue
Block a user