summaryrefslogtreecommitdiffhomepage
path: root/device.h
blob: e11df1f224e8de0b69ceb189fe4b7edd8938188b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#ifndef __LL_H
#define __LL_H

#include <libubox/avl.h>
#include <netinet/in.h>

struct device;
struct device_hotplug_ops;

typedef int (*device_state_cb)(struct device *, bool up);

enum {
	DEV_ATTR_TYPE,
	DEV_ATTR_NAME,
	DEV_ATTR_IFNAME,
	DEV_ATTR_MTU,
	DEV_ATTR_MACADDR,
	DEV_ATTR_TXQUEUELEN,
	__DEV_ATTR_MAX,
};

struct device_type {
	struct list_head list;
	const char *name;

	const struct config_param_list *config_params;

	struct device *(*create)(struct blob_attr *attr);
	void (*dump_status)(struct device *, struct blob_buf *buf);
	int (*check_state)(struct device *);
	void (*free)(struct device *);
};

enum {
	DEV_OPT_MTU		= (1 << 0),
	DEV_OPT_MACADDR		= (1 << 1),
	DEV_OPT_TXQUEUELEN	= (1 << 2)
};

enum device_addr_flags {
	/* address family for routes and addresses */
	DEVADDR_INET4	= (0 << 0),
	DEVADDR_INET6	= (1 << 0),
	DEVADDR_FAMILY	= DEVADDR_INET4 | DEVADDR_INET6,

	/* device route (no gateway) */
	DEVADDR_DEVICE	= (1 << 1),
};

union if_addr {
	struct in_addr in;
	struct in6_addr in6;
};

struct device_addr {
	struct list_head list;
	void *ctx;

	enum device_addr_flags flags;

	unsigned int mask;
	union if_addr addr;
};

struct device_route {
	struct list_head list;
	void *ctx;

	enum device_addr_flags flags;

	unsigned int mask;
	union if_addr addr;
	union if_addr nexthop;
};

/* 
 * link layer device. typically represents a linux network device.
 * can be used to support VLANs as well
 */
struct device {
	const struct device_type *type;

	struct avl_node avl;
	struct list_head users;

	char ifname[IFNAMSIZ + 1];
	int ifindex;

	bool present;
	int active;

	/* set interface up or down */
	device_state_cb set_state;

	const struct device_hotplug_ops *hotplug_ops;

	/* settings */
	unsigned int flags;

	unsigned int mtu;
	unsigned int txqueuelen;
	uint8_t macaddr[6];

	uint32_t config_hash;
};

/* events broadcasted to all users of a device */
enum device_event {
	DEV_EVENT_ADD,
	DEV_EVENT_REMOVE,

	DEV_EVENT_SETUP,
	DEV_EVENT_TEARDOWN,
	DEV_EVENT_UP,
	DEV_EVENT_DOWN,

	DEV_EVENT_LINK_UP,
	DEV_EVENT_LINK_DOWN,
};

/*
 * device dependency with callbacks
 */
struct device_user {
	struct list_head list;

	struct device *dev;
	void (*cb)(struct device_user *, enum device_event);
};

struct device_hotplug_ops {
	int (*add)(struct device *main, struct device *member);
	int (*del)(struct device *main, struct device *member);
};

extern const struct config_param_list device_attr_list;
extern const struct device_type simple_device_type;
extern const struct device_type bridge_device_type;

void device_init_settings(struct device *dev, struct blob_attr **tb);

void device_init_virtual(struct device *dev, const struct device_type *type, const char *name);
int device_init(struct device *iface, const struct device_type *type, const char *ifname);
void device_cleanup(struct device *iface);
struct device *device_get(const char *name, bool create);
void device_add_user(struct device_user *dep, struct device *iface);
void device_remove_user(struct device_user *dep);

void device_set_present(struct device *dev, bool state);
int device_claim(struct device *dev);
void device_release(struct device *dev);
int check_device_state(struct device *dev);

static inline void
device_free(struct device *dev)
{
	dev->type->free(dev);
}

void device_free_all(void);

struct device *get_vlan_device_chain(const char *ifname, bool create);

#endif