Viewing file: switchdev.h (13.96 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * include/net/switchdev.h - Switch device API * Copyright (c) 2014-2015 Jiri Pirko <[email protected]> * Copyright (c) 2014-2015 Scott Feldman <[email protected]> */ #ifndef _LINUX_SWITCHDEV_H_ #define _LINUX_SWITCHDEV_H_
#include <linux/netdevice.h> #include <linux/notifier.h> #include <linux/list.h> #include <net/ip_fib.h>
#define SWITCHDEV_F_NO_RECURSE BIT(0) #define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1) #define SWITCHDEV_F_DEFER BIT(2)
enum switchdev_attr_id { SWITCHDEV_ATTR_ID_UNDEFINED, SWITCHDEV_ATTR_ID_PORT_STP_STATE, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_MROUTER, SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL, SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED, SWITCHDEV_ATTR_ID_BRIDGE_MROUTER, SWITCHDEV_ATTR_ID_MRP_PORT_ROLE, };
struct switchdev_brport_flags { unsigned long val; unsigned long mask; };
struct switchdev_attr { struct net_device *orig_dev; enum switchdev_attr_id id; u32 flags; void *complete_priv; void (*complete)(struct net_device *dev, int err, void *priv); union { u8 stp_state; /* PORT_STP_STATE */ struct switchdev_brport_flags brport_flags; /* PORT_BRIDGE_FLAGS */ bool mrouter; /* PORT_MROUTER */ clock_t ageing_time; /* BRIDGE_AGEING_TIME */ bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */ u16 vlan_protocol; /* BRIDGE_VLAN_PROTOCOL */ bool mc_disabled; /* MC_DISABLED */ u8 mrp_port_role; /* MRP_PORT_ROLE */ } u; };
enum switchdev_obj_id { SWITCHDEV_OBJ_ID_UNDEFINED, SWITCHDEV_OBJ_ID_PORT_VLAN, SWITCHDEV_OBJ_ID_PORT_MDB, SWITCHDEV_OBJ_ID_HOST_MDB, SWITCHDEV_OBJ_ID_MRP, SWITCHDEV_OBJ_ID_RING_TEST_MRP, SWITCHDEV_OBJ_ID_RING_ROLE_MRP, SWITCHDEV_OBJ_ID_RING_STATE_MRP, SWITCHDEV_OBJ_ID_IN_TEST_MRP, SWITCHDEV_OBJ_ID_IN_ROLE_MRP, SWITCHDEV_OBJ_ID_IN_STATE_MRP, };
struct switchdev_obj { struct list_head list; struct net_device *orig_dev; enum switchdev_obj_id id; u32 flags; void *complete_priv; void (*complete)(struct net_device *dev, int err, void *priv); };
/* SWITCHDEV_OBJ_ID_PORT_VLAN */ struct switchdev_obj_port_vlan { struct switchdev_obj obj; u16 flags; u16 vid; };
#define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \ container_of((OBJ), struct switchdev_obj_port_vlan, obj)
/* SWITCHDEV_OBJ_ID_PORT_MDB */ struct switchdev_obj_port_mdb { struct switchdev_obj obj; unsigned char addr[ETH_ALEN]; u16 vid; };
#define SWITCHDEV_OBJ_PORT_MDB(OBJ) \ container_of((OBJ), struct switchdev_obj_port_mdb, obj)
/* SWITCHDEV_OBJ_ID_MRP */ struct switchdev_obj_mrp { struct switchdev_obj obj; struct net_device *p_port; struct net_device *s_port; u32 ring_id; u16 prio; };
#define SWITCHDEV_OBJ_MRP(OBJ) \ container_of((OBJ), struct switchdev_obj_mrp, obj)
/* SWITCHDEV_OBJ_ID_RING_TEST_MRP */ struct switchdev_obj_ring_test_mrp { struct switchdev_obj obj; /* The value is in us and a value of 0 represents to stop */ u32 interval; u8 max_miss; u32 ring_id; u32 period; bool monitor; };
#define SWITCHDEV_OBJ_RING_TEST_MRP(OBJ) \ container_of((OBJ), struct switchdev_obj_ring_test_mrp, obj)
/* SWICHDEV_OBJ_ID_RING_ROLE_MRP */ struct switchdev_obj_ring_role_mrp { struct switchdev_obj obj; u8 ring_role; u32 ring_id; u8 sw_backup; };
#define SWITCHDEV_OBJ_RING_ROLE_MRP(OBJ) \ container_of((OBJ), struct switchdev_obj_ring_role_mrp, obj)
struct switchdev_obj_ring_state_mrp { struct switchdev_obj obj; u8 ring_state; u32 ring_id; };
#define SWITCHDEV_OBJ_RING_STATE_MRP(OBJ) \ container_of((OBJ), struct switchdev_obj_ring_state_mrp, obj)
/* SWITCHDEV_OBJ_ID_IN_TEST_MRP */ struct switchdev_obj_in_test_mrp { struct switchdev_obj obj; /* The value is in us and a value of 0 represents to stop */ u32 interval; u32 in_id; u32 period; u8 max_miss; };
#define SWITCHDEV_OBJ_IN_TEST_MRP(OBJ) \ container_of((OBJ), struct switchdev_obj_in_test_mrp, obj)
/* SWICHDEV_OBJ_ID_IN_ROLE_MRP */ struct switchdev_obj_in_role_mrp { struct switchdev_obj obj; struct net_device *i_port; u32 ring_id; u16 in_id; u8 in_role; u8 sw_backup; };
#define SWITCHDEV_OBJ_IN_ROLE_MRP(OBJ) \ container_of((OBJ), struct switchdev_obj_in_role_mrp, obj)
struct switchdev_obj_in_state_mrp { struct switchdev_obj obj; u32 in_id; u8 in_state; };
#define SWITCHDEV_OBJ_IN_STATE_MRP(OBJ) \ container_of((OBJ), struct switchdev_obj_in_state_mrp, obj)
typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj);
struct switchdev_brport { struct net_device *dev; const void *ctx; struct notifier_block *atomic_nb; struct notifier_block *blocking_nb; bool tx_fwd_offload; };
enum switchdev_notifier_type { SWITCHDEV_FDB_ADD_TO_BRIDGE = 1, SWITCHDEV_FDB_DEL_TO_BRIDGE, SWITCHDEV_FDB_ADD_TO_DEVICE, SWITCHDEV_FDB_DEL_TO_DEVICE, SWITCHDEV_FDB_OFFLOADED, SWITCHDEV_FDB_FLUSH_TO_BRIDGE,
SWITCHDEV_PORT_OBJ_ADD, /* Blocking. */ SWITCHDEV_PORT_OBJ_DEL, /* Blocking. */ SWITCHDEV_PORT_ATTR_SET, /* May be blocking . */
SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE, SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE, SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE, SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE, SWITCHDEV_VXLAN_FDB_OFFLOADED,
SWITCHDEV_BRPORT_OFFLOADED, SWITCHDEV_BRPORT_UNOFFLOADED, };
struct switchdev_notifier_info { struct net_device *dev; struct netlink_ext_ack *extack; const void *ctx; };
struct switchdev_notifier_fdb_info { struct switchdev_notifier_info info; /* must be first */ const unsigned char *addr; u16 vid; u8 added_by_user:1, is_local:1, offloaded:1; };
struct switchdev_notifier_port_obj_info { struct switchdev_notifier_info info; /* must be first */ const struct switchdev_obj *obj; bool handled; };
struct switchdev_notifier_port_attr_info { struct switchdev_notifier_info info; /* must be first */ const struct switchdev_attr *attr; bool handled; };
struct switchdev_notifier_brport_info { struct switchdev_notifier_info info; /* must be first */ const struct switchdev_brport brport; };
static inline struct net_device * switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info) { return info->dev; }
static inline struct netlink_ext_ack * switchdev_notifier_info_to_extack(const struct switchdev_notifier_info *info) { return info->extack; }
static inline bool switchdev_fdb_is_dynamically_learned(const struct switchdev_notifier_fdb_info *fdb_info) { return !fdb_info->added_by_user && !fdb_info->is_local; }
#ifdef CONFIG_NET_SWITCHDEV
int switchdev_bridge_port_offload(struct net_device *brport_dev, struct net_device *dev, const void *ctx, struct notifier_block *atomic_nb, struct notifier_block *blocking_nb, bool tx_fwd_offload, struct netlink_ext_ack *extack); void switchdev_bridge_port_unoffload(struct net_device *brport_dev, const void *ctx, struct notifier_block *atomic_nb, struct notifier_block *blocking_nb);
void switchdev_deferred_process(void); int switchdev_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr, struct netlink_ext_ack *extack); int switchdev_port_obj_add(struct net_device *dev, const struct switchdev_obj *obj, struct netlink_ext_ack *extack); int switchdev_port_obj_del(struct net_device *dev, const struct switchdev_obj *obj);
int register_switchdev_notifier(struct notifier_block *nb); int unregister_switchdev_notifier(struct notifier_block *nb); int call_switchdev_notifiers(unsigned long val, struct net_device *dev, struct switchdev_notifier_info *info, struct netlink_ext_ack *extack);
int register_switchdev_blocking_notifier(struct notifier_block *nb); int unregister_switchdev_blocking_notifier(struct notifier_block *nb); int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, struct switchdev_notifier_info *info, struct netlink_ext_ack *extack);
void switchdev_port_fwd_mark_set(struct net_device *dev, struct net_device *group_dev, bool joining);
int switchdev_handle_fdb_add_to_device(struct net_device *dev, const struct switchdev_notifier_fdb_info *fdb_info, bool (*check_cb)(const struct net_device *dev), bool (*foreign_dev_check_cb)(const struct net_device *dev, const struct net_device *foreign_dev), int (*add_cb)(struct net_device *dev, const struct net_device *orig_dev, const void *ctx, const struct switchdev_notifier_fdb_info *fdb_info), int (*lag_add_cb)(struct net_device *dev, const struct net_device *orig_dev, const void *ctx, const struct switchdev_notifier_fdb_info *fdb_info));
int switchdev_handle_fdb_del_to_device(struct net_device *dev, const struct switchdev_notifier_fdb_info *fdb_info, bool (*check_cb)(const struct net_device *dev), bool (*foreign_dev_check_cb)(const struct net_device *dev, const struct net_device *foreign_dev), int (*del_cb)(struct net_device *dev, const struct net_device *orig_dev, const void *ctx, const struct switchdev_notifier_fdb_info *fdb_info), int (*lag_del_cb)(struct net_device *dev, const struct net_device *orig_dev, const void *ctx, const struct switchdev_notifier_fdb_info *fdb_info));
int switchdev_handle_port_obj_add(struct net_device *dev, struct switchdev_notifier_port_obj_info *port_obj_info, bool (*check_cb)(const struct net_device *dev), int (*add_cb)(struct net_device *dev, const void *ctx, const struct switchdev_obj *obj, struct netlink_ext_ack *extack)); int switchdev_handle_port_obj_del(struct net_device *dev, struct switchdev_notifier_port_obj_info *port_obj_info, bool (*check_cb)(const struct net_device *dev), int (*del_cb)(struct net_device *dev, const void *ctx, const struct switchdev_obj *obj));
int switchdev_handle_port_attr_set(struct net_device *dev, struct switchdev_notifier_port_attr_info *port_attr_info, bool (*check_cb)(const struct net_device *dev), int (*set_cb)(struct net_device *dev, const void *ctx, const struct switchdev_attr *attr, struct netlink_ext_ack *extack)); #else
static inline int switchdev_bridge_port_offload(struct net_device *brport_dev, struct net_device *dev, const void *ctx, struct notifier_block *atomic_nb, struct notifier_block *blocking_nb, bool tx_fwd_offload, struct netlink_ext_ack *extack) { return -EOPNOTSUPP; }
static inline void switchdev_bridge_port_unoffload(struct net_device *brport_dev, const void *ctx, struct notifier_block *atomic_nb, struct notifier_block *blocking_nb) { }
static inline void switchdev_deferred_process(void) { }
static inline int switchdev_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr, struct netlink_ext_ack *extack) { return -EOPNOTSUPP; }
static inline int switchdev_port_obj_add(struct net_device *dev, const struct switchdev_obj *obj, struct netlink_ext_ack *extack) { return -EOPNOTSUPP; }
static inline int switchdev_port_obj_del(struct net_device *dev, const struct switchdev_obj *obj) { return -EOPNOTSUPP; }
static inline int register_switchdev_notifier(struct notifier_block *nb) { return 0; }
static inline int unregister_switchdev_notifier(struct notifier_block *nb) { return 0; }
static inline int call_switchdev_notifiers(unsigned long val, struct net_device *dev, struct switchdev_notifier_info *info, struct netlink_ext_ack *extack) { return NOTIFY_DONE; }
static inline int register_switchdev_blocking_notifier(struct notifier_block *nb) { return 0; }
static inline int unregister_switchdev_blocking_notifier(struct notifier_block *nb) { return 0; }
static inline int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, struct switchdev_notifier_info *info, struct netlink_ext_ack *extack) { return NOTIFY_DONE; }
static inline int switchdev_handle_fdb_add_to_device(struct net_device *dev, const struct switchdev_notifier_fdb_info *fdb_info, bool (*check_cb)(const struct net_device *dev), bool (*foreign_dev_check_cb)(const struct net_device *dev, const struct net_device *foreign_dev), int (*add_cb)(struct net_device *dev, const struct net_device *orig_dev, const void *ctx, const struct switchdev_notifier_fdb_info *fdb_info), int (*lag_add_cb)(struct net_device *dev, const struct net_device *orig_dev, const void *ctx, const struct switchdev_notifier_fdb_info *fdb_info)) { return 0; }
static inline int switchdev_handle_fdb_del_to_device(struct net_device *dev, const struct switchdev_notifier_fdb_info *fdb_info, bool (*check_cb)(const struct net_device *dev), bool (*foreign_dev_check_cb)(const struct net_device *dev, const struct net_device *foreign_dev), int (*del_cb)(struct net_device *dev, const struct net_device *orig_dev, const void *ctx, const struct switchdev_notifier_fdb_info *fdb_info), int (*lag_del_cb)(struct net_device *dev, const struct net_device *orig_dev, const void *ctx, const struct switchdev_notifier_fdb_info *fdb_info)) { return 0; }
static inline int switchdev_handle_port_obj_add(struct net_device *dev, struct switchdev_notifier_port_obj_info *port_obj_info, bool (*check_cb)(const struct net_device *dev), int (*add_cb)(struct net_device *dev, const void *ctx, const struct switchdev_obj *obj, struct netlink_ext_ack *extack)) { return 0; }
static inline int switchdev_handle_port_obj_del(struct net_device *dev, struct switchdev_notifier_port_obj_info *port_obj_info, bool (*check_cb)(const struct net_device *dev), int (*del_cb)(struct net_device *dev, const void *ctx, const struct switchdev_obj *obj)) { return 0; }
static inline int switchdev_handle_port_attr_set(struct net_device *dev, struct switchdev_notifier_port_attr_info *port_attr_info, bool (*check_cb)(const struct net_device *dev), int (*set_cb)(struct net_device *dev, const void *ctx, const struct switchdev_attr *attr, struct netlink_ext_ack *extack)) { return 0; } #endif
#endif /* _LINUX_SWITCHDEV_H_ */
|