switchdev.h 6.6 KB
Newer Older
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 7 8 9 10 11 12 13 14
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */
#ifndef _LINUX_SWITCHDEV_H_
#define _LINUX_SWITCHDEV_H_

#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 24 25 26 27 28 29 30
struct switchdev_trans_item {
	struct list_head list;
	void *data;
	void (*destructor)(const void *data);
};

struct switchdev_trans {
	struct list_head item_list;
31
	bool ph_prepare;
32 33
};

34 35
static inline bool switchdev_trans_ph_prepare(struct switchdev_trans *trans)
{
36
	return trans && trans->ph_prepare;
37 38 39 40
}

static inline bool switchdev_trans_ph_commit(struct switchdev_trans *trans)
{
41
	return trans && !trans->ph_prepare;
42 43
}

44
enum switchdev_attr_id {
45 46 47 48
	SWITCHDEV_ATTR_ID_UNDEFINED,
	SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
	SWITCHDEV_ATTR_ID_PORT_STP_STATE,
	SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
49
	SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
50
	SWITCHDEV_ATTR_ID_PORT_MROUTER,
51
	SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
52
	SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING,
53
	SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED,
54
	SWITCHDEV_ATTR_ID_BRIDGE_MROUTER,
55 56 57
};

struct switchdev_attr {
58
	struct net_device *orig_dev;
59 60
	enum switchdev_attr_id id;
	u32 flags;
61 62
	void *complete_priv;
	void (*complete)(struct net_device *dev, int err, void *priv);
63 64
	union {
		struct netdev_phys_item_id ppid;	/* PORT_PARENT_ID */
65
		u8 stp_state;				/* PORT_STP_STATE */
66
		unsigned long brport_flags;		/* PORT_BRIDGE_FLAGS */
67
		unsigned long brport_flags_support;	/* PORT_BRIDGE_FLAGS_SUPPORT */
68
		bool mrouter;				/* PORT_MROUTER */
69
		clock_t ageing_time;			/* BRIDGE_AGEING_TIME */
70
		bool vlan_filtering;			/* BRIDGE_VLAN_FILTERING */
71
		bool mc_disabled;			/* MC_DISABLED */
72
	} u;
73 74
};

75
enum switchdev_obj_id {
76 77
	SWITCHDEV_OBJ_ID_UNDEFINED,
	SWITCHDEV_OBJ_ID_PORT_VLAN,
E
Elad Raz 已提交
78
	SWITCHDEV_OBJ_ID_PORT_MDB,
79
	SWITCHDEV_OBJ_ID_HOST_MDB,
80 81
};

82
struct switchdev_obj {
83
	struct net_device *orig_dev;
84
	enum switchdev_obj_id id;
85
	u32 flags;
86 87
	void *complete_priv;
	void (*complete)(struct net_device *dev, int err, void *priv);
88 89
};

90
/* SWITCHDEV_OBJ_ID_PORT_VLAN */
91
struct switchdev_obj_port_vlan {
92
	struct switchdev_obj obj;
93 94 95 96 97
	u16 flags;
	u16 vid_begin;
	u16 vid_end;
};

98 99 100
#define SWITCHDEV_OBJ_PORT_VLAN(obj) \
	container_of(obj, struct switchdev_obj_port_vlan, obj)

E
Elad Raz 已提交
101 102 103 104 105 106 107 108 109 110
/* 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)

111 112 113 114 115
void switchdev_trans_item_enqueue(struct switchdev_trans *trans,
				  void *data, void (*destructor)(void const *),
				  struct switchdev_trans_item *tritem);
void *switchdev_trans_item_dequeue(struct switchdev_trans *trans);

116 117
typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj);

S
Scott Feldman 已提交
118 119 120
/**
 * struct switchdev_ops - switchdev operations
 *
121 122 123 124
 * @switchdev_port_attr_get: Get a port attribute (see switchdev_attr).
 *
 * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr).
 *
125
 * @switchdev_port_obj_add: Add an object to port (see switchdev_obj_*).
126
 *
127
 * @switchdev_port_obj_del: Delete an object from port (see switchdev_obj_*).
S
Scott Feldman 已提交
128
 */
J
Jiri Pirko 已提交
129
struct switchdev_ops {
130 131 132
	int	(*switchdev_port_attr_get)(struct net_device *dev,
					   struct switchdev_attr *attr);
	int	(*switchdev_port_attr_set)(struct net_device *dev,
133
					   const struct switchdev_attr *attr,
134
					   struct switchdev_trans *trans);
135
	int	(*switchdev_port_obj_add)(struct net_device *dev,
136
					  const struct switchdev_obj *obj,
137
					  struct switchdev_trans *trans);
138
	int	(*switchdev_port_obj_del)(struct net_device *dev,
139
					  const struct switchdev_obj *obj);
S
Scott Feldman 已提交
140 141
};

142
enum switchdev_notifier_type {
143 144 145 146
	SWITCHDEV_FDB_ADD_TO_BRIDGE = 1,
	SWITCHDEV_FDB_DEL_TO_BRIDGE,
	SWITCHDEV_FDB_ADD_TO_DEVICE,
	SWITCHDEV_FDB_DEL_TO_DEVICE,
147
	SWITCHDEV_FDB_OFFLOADED,
P
Petr Machata 已提交
148 149 150

	SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
	SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE,
151 152
};

153
struct switchdev_notifier_info {
154 155 156
	struct net_device *dev;
};

157 158
struct switchdev_notifier_fdb_info {
	struct switchdev_notifier_info info; /* must be first */
159 160
	const unsigned char *addr;
	u16 vid;
161
	bool added_by_user;
162 163
};

164
static inline struct net_device *
165
switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info)
166 167 168
{
	return info->dev;
}
169 170 171

#ifdef CONFIG_NET_SWITCHDEV

172
void switchdev_deferred_process(void);
173 174 175
int switchdev_port_attr_get(struct net_device *dev,
			    struct switchdev_attr *attr);
int switchdev_port_attr_set(struct net_device *dev,
176
			    const struct switchdev_attr *attr);
177
int switchdev_port_obj_add(struct net_device *dev,
178
			   const struct switchdev_obj *obj);
179
int switchdev_port_obj_del(struct net_device *dev,
180
			   const struct switchdev_obj *obj);
181 182 183 184
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);
185 186 187
void switchdev_port_fwd_mark_set(struct net_device *dev,
				 struct net_device *group_dev,
				 bool joining);
188

189 190
bool switchdev_port_same_parent_id(struct net_device *a,
				   struct net_device *b);
191 192

#define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops))
193 194
#else

195 196 197 198
static inline void switchdev_deferred_process(void)
{
}

199 200 201 202 203 204 205
static inline int switchdev_port_attr_get(struct net_device *dev,
					  struct switchdev_attr *attr)
{
	return -EOPNOTSUPP;
}

static inline int switchdev_port_attr_set(struct net_device *dev,
206
					  const struct switchdev_attr *attr)
207 208 209 210
{
	return -EOPNOTSUPP;
}

211
static inline int switchdev_port_obj_add(struct net_device *dev,
212
					 const struct switchdev_obj *obj)
213 214 215 216 217
{
	return -EOPNOTSUPP;
}

static inline int switchdev_port_obj_del(struct net_device *dev,
218
					 const struct switchdev_obj *obj)
219 220 221 222
{
	return -EOPNOTSUPP;
}

223
static inline int register_switchdev_notifier(struct notifier_block *nb)
224 225 226 227
{
	return 0;
}

228
static inline int unregister_switchdev_notifier(struct notifier_block *nb)
229 230 231 232
{
	return 0;
}

233 234 235
static inline int call_switchdev_notifiers(unsigned long val,
					   struct net_device *dev,
					   struct switchdev_notifier_info *info)
236 237 238 239
{
	return NOTIFY_DONE;
}

240 241 242 243 244 245
static inline bool switchdev_port_same_parent_id(struct net_device *a,
						 struct net_device *b)
{
	return false;
}

246 247
#define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0)

248 249 250
#endif

#endif /* _LINUX_SWITCHDEV_H_ */