1 /* 2 * include/net/switchdev.h - Switch device API 3 * Copyright (c) 2014-2015 Jiri Pirko <jiri@resnulli.us> 4 * Copyright (c) 2014-2015 Scott Feldman <sfeldma@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 #ifndef _LINUX_SWITCHDEV_H_ 12 #define _LINUX_SWITCHDEV_H_ 13 14 #include <linux/netdevice.h> 15 #include <linux/notifier.h> 16 #include <linux/list.h> 17 #include <net/ip_fib.h> 18 19 #define SWITCHDEV_F_NO_RECURSE BIT(0) 20 #define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1) 21 #define SWITCHDEV_F_DEFER BIT(2) 22 23 struct switchdev_trans_item { 24 struct list_head list; 25 void *data; 26 void (*destructor)(const void *data); 27 }; 28 29 struct switchdev_trans { 30 struct list_head item_list; 31 bool ph_prepare; 32 }; 33 34 static inline bool switchdev_trans_ph_prepare(struct switchdev_trans *trans) 35 { 36 return trans && trans->ph_prepare; 37 } 38 39 static inline bool switchdev_trans_ph_commit(struct switchdev_trans *trans) 40 { 41 return trans && !trans->ph_prepare; 42 } 43 44 enum switchdev_attr_id { 45 SWITCHDEV_ATTR_ID_UNDEFINED, 46 SWITCHDEV_ATTR_ID_PORT_STP_STATE, 47 SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, 48 SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, 49 SWITCHDEV_ATTR_ID_PORT_MROUTER, 50 SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, 51 SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 52 SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED, 53 SWITCHDEV_ATTR_ID_BRIDGE_MROUTER, 54 }; 55 56 struct switchdev_attr { 57 struct net_device *orig_dev; 58 enum switchdev_attr_id id; 59 u32 flags; 60 void *complete_priv; 61 void (*complete)(struct net_device *dev, int err, void *priv); 62 union { 63 u8 stp_state; /* PORT_STP_STATE */ 64 unsigned long brport_flags; /* PORT_BRIDGE_FLAGS */ 65 unsigned long brport_flags_support; /* PORT_BRIDGE_FLAGS_SUPPORT */ 66 bool mrouter; /* PORT_MROUTER */ 67 clock_t ageing_time; /* BRIDGE_AGEING_TIME */ 68 bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */ 69 bool mc_disabled; /* MC_DISABLED */ 70 } u; 71 }; 72 73 enum switchdev_obj_id { 74 SWITCHDEV_OBJ_ID_UNDEFINED, 75 SWITCHDEV_OBJ_ID_PORT_VLAN, 76 SWITCHDEV_OBJ_ID_PORT_MDB, 77 SWITCHDEV_OBJ_ID_HOST_MDB, 78 }; 79 80 struct switchdev_obj { 81 struct net_device *orig_dev; 82 enum switchdev_obj_id id; 83 u32 flags; 84 void *complete_priv; 85 void (*complete)(struct net_device *dev, int err, void *priv); 86 }; 87 88 /* SWITCHDEV_OBJ_ID_PORT_VLAN */ 89 struct switchdev_obj_port_vlan { 90 struct switchdev_obj obj; 91 u16 flags; 92 u16 vid_begin; 93 u16 vid_end; 94 }; 95 96 #define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \ 97 container_of((OBJ), struct switchdev_obj_port_vlan, obj) 98 99 /* SWITCHDEV_OBJ_ID_PORT_MDB */ 100 struct switchdev_obj_port_mdb { 101 struct switchdev_obj obj; 102 unsigned char addr[ETH_ALEN]; 103 u16 vid; 104 }; 105 106 #define SWITCHDEV_OBJ_PORT_MDB(OBJ) \ 107 container_of((OBJ), struct switchdev_obj_port_mdb, obj) 108 109 void switchdev_trans_item_enqueue(struct switchdev_trans *trans, 110 void *data, void (*destructor)(void const *), 111 struct switchdev_trans_item *tritem); 112 void *switchdev_trans_item_dequeue(struct switchdev_trans *trans); 113 114 typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj); 115 116 /** 117 * struct switchdev_ops - switchdev operations 118 * 119 * @switchdev_port_attr_get: Get a port attribute (see switchdev_attr). 120 * 121 * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr). 122 */ 123 struct switchdev_ops { 124 int (*switchdev_port_attr_get)(struct net_device *dev, 125 struct switchdev_attr *attr); 126 int (*switchdev_port_attr_set)(struct net_device *dev, 127 const struct switchdev_attr *attr, 128 struct switchdev_trans *trans); 129 }; 130 131 enum switchdev_notifier_type { 132 SWITCHDEV_FDB_ADD_TO_BRIDGE = 1, 133 SWITCHDEV_FDB_DEL_TO_BRIDGE, 134 SWITCHDEV_FDB_ADD_TO_DEVICE, 135 SWITCHDEV_FDB_DEL_TO_DEVICE, 136 SWITCHDEV_FDB_OFFLOADED, 137 138 SWITCHDEV_PORT_OBJ_ADD, /* Blocking. */ 139 SWITCHDEV_PORT_OBJ_DEL, /* Blocking. */ 140 141 SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE, 142 SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE, 143 SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE, 144 SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE, 145 SWITCHDEV_VXLAN_FDB_OFFLOADED, 146 }; 147 148 struct switchdev_notifier_info { 149 struct net_device *dev; 150 struct netlink_ext_ack *extack; 151 }; 152 153 struct switchdev_notifier_fdb_info { 154 struct switchdev_notifier_info info; /* must be first */ 155 const unsigned char *addr; 156 u16 vid; 157 u8 added_by_user:1, 158 offloaded:1; 159 }; 160 161 struct switchdev_notifier_port_obj_info { 162 struct switchdev_notifier_info info; /* must be first */ 163 const struct switchdev_obj *obj; 164 struct switchdev_trans *trans; 165 bool handled; 166 }; 167 168 static inline struct net_device * 169 switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info) 170 { 171 return info->dev; 172 } 173 174 static inline struct netlink_ext_ack * 175 switchdev_notifier_info_to_extack(const struct switchdev_notifier_info *info) 176 { 177 return info->extack; 178 } 179 180 #ifdef CONFIG_NET_SWITCHDEV 181 182 void switchdev_deferred_process(void); 183 int switchdev_port_attr_get(struct net_device *dev, 184 struct switchdev_attr *attr); 185 int switchdev_port_attr_set(struct net_device *dev, 186 const struct switchdev_attr *attr); 187 int switchdev_port_obj_add(struct net_device *dev, 188 const struct switchdev_obj *obj, 189 struct netlink_ext_ack *extack); 190 int switchdev_port_obj_del(struct net_device *dev, 191 const struct switchdev_obj *obj); 192 193 int register_switchdev_notifier(struct notifier_block *nb); 194 int unregister_switchdev_notifier(struct notifier_block *nb); 195 int call_switchdev_notifiers(unsigned long val, struct net_device *dev, 196 struct switchdev_notifier_info *info, 197 struct netlink_ext_ack *extack); 198 199 int register_switchdev_blocking_notifier(struct notifier_block *nb); 200 int unregister_switchdev_blocking_notifier(struct notifier_block *nb); 201 int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, 202 struct switchdev_notifier_info *info, 203 struct netlink_ext_ack *extack); 204 205 void switchdev_port_fwd_mark_set(struct net_device *dev, 206 struct net_device *group_dev, 207 bool joining); 208 209 int switchdev_handle_port_obj_add(struct net_device *dev, 210 struct switchdev_notifier_port_obj_info *port_obj_info, 211 bool (*check_cb)(const struct net_device *dev), 212 int (*add_cb)(struct net_device *dev, 213 const struct switchdev_obj *obj, 214 struct switchdev_trans *trans, 215 struct netlink_ext_ack *extack)); 216 int switchdev_handle_port_obj_del(struct net_device *dev, 217 struct switchdev_notifier_port_obj_info *port_obj_info, 218 bool (*check_cb)(const struct net_device *dev), 219 int (*del_cb)(struct net_device *dev, 220 const struct switchdev_obj *obj)); 221 222 #define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops)) 223 #else 224 225 static inline void switchdev_deferred_process(void) 226 { 227 } 228 229 static inline int switchdev_port_attr_get(struct net_device *dev, 230 struct switchdev_attr *attr) 231 { 232 return -EOPNOTSUPP; 233 } 234 235 static inline int switchdev_port_attr_set(struct net_device *dev, 236 const struct switchdev_attr *attr) 237 { 238 return -EOPNOTSUPP; 239 } 240 241 static inline int switchdev_port_obj_add(struct net_device *dev, 242 const struct switchdev_obj *obj, 243 struct netlink_ext_ack *extack) 244 { 245 return -EOPNOTSUPP; 246 } 247 248 static inline int switchdev_port_obj_del(struct net_device *dev, 249 const struct switchdev_obj *obj) 250 { 251 return -EOPNOTSUPP; 252 } 253 254 static inline int register_switchdev_notifier(struct notifier_block *nb) 255 { 256 return 0; 257 } 258 259 static inline int unregister_switchdev_notifier(struct notifier_block *nb) 260 { 261 return 0; 262 } 263 264 static inline int call_switchdev_notifiers(unsigned long val, 265 struct net_device *dev, 266 struct switchdev_notifier_info *info, 267 struct netlink_ext_ack *extack) 268 { 269 return NOTIFY_DONE; 270 } 271 272 static inline int 273 register_switchdev_blocking_notifier(struct notifier_block *nb) 274 { 275 return 0; 276 } 277 278 static inline int 279 unregister_switchdev_blocking_notifier(struct notifier_block *nb) 280 { 281 return 0; 282 } 283 284 static inline int 285 call_switchdev_blocking_notifiers(unsigned long val, 286 struct net_device *dev, 287 struct switchdev_notifier_info *info, 288 struct netlink_ext_ack *extack) 289 { 290 return NOTIFY_DONE; 291 } 292 293 static inline int 294 switchdev_handle_port_obj_add(struct net_device *dev, 295 struct switchdev_notifier_port_obj_info *port_obj_info, 296 bool (*check_cb)(const struct net_device *dev), 297 int (*add_cb)(struct net_device *dev, 298 const struct switchdev_obj *obj, 299 struct switchdev_trans *trans, 300 struct netlink_ext_ack *extack)) 301 { 302 return 0; 303 } 304 305 static inline int 306 switchdev_handle_port_obj_del(struct net_device *dev, 307 struct switchdev_notifier_port_obj_info *port_obj_info, 308 bool (*check_cb)(const struct net_device *dev), 309 int (*del_cb)(struct net_device *dev, 310 const struct switchdev_obj *obj)) 311 { 312 return 0; 313 } 314 315 #define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0) 316 317 #endif 318 319 #endif /* _LINUX_SWITCHDEV_H_ */ 320