3
* @brief Protocol independent device support routines.
6
* @author Anton Bondarev
17
#include <lib/libds/hashtable.h>
18
#include <lib/libds/dlist.h>
19
#include <lib/libds/indexator.h>
20
#include <lib/libds/array.h>
22
#include <mem/misc/pool.h>
23
#include <mem/sysmalloc.h>
26
#include <net/netdevice.h>
27
#include <net/skbuff.h>
28
#include <net/netlink.h>
30
#include <framework/mod/options.h>
32
#define MODOPS_NETDEV_QUANTITY OPTION_GET(NUMBER, netdev_quantity)
33
#define MODOPS_NETDEV_TABLE_SZ OPTION_GET(NUMBER, netdev_table_sz)
35
POOL_DEF(netdev_pool, struct net_device, MODOPS_NETDEV_QUANTITY);
37
INDEX_DEF(netdev_index, 1, MODOPS_NETDEV_QUANTITY);
39
static size_t netdev_hash(void *key) {
41
const char *name = key;
44
while (*name != '\0') {
51
HASHTABLE_DEF(nd_ht, MODOPS_NETDEV_TABLE_SZ, &netdev_hash, (ht_cmp_ft)&strcmp);
52
struct hashtable *netdevs_table = &nd_ht;
54
POOL_DEF(netdev_htitem_pool, struct hashtable_item, MODOPS_NETDEV_QUANTITY);
56
static int netdev_init(struct net_device *dev, const char *name,
57
int (*setup)(struct net_device *), size_t priv_size) {
60
assert(setup != NULL);
62
dlist_head_init(&dev->rx_lnk);
63
dlist_head_init(&dev->tx_lnk);
64
strcpy(&dev->name[0], name);
65
memset(&dev->stats, 0, sizeof dev->stats);
66
skb_queue_init(&dev->dev_queue);
67
skb_queue_init(&dev->dev_queue_tx);
70
dev->priv = sysmalloc(priv_size);
71
if (dev->priv == NULL) {
82
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
83
void dev_net_set(struct net_device *dev, net_namespace_p net_ns) {
84
assign_net_ns(dev->net_ns, net_ns);
88
struct net_device * netdev_alloc(const char *name,
89
int (*setup)(struct net_device *), size_t priv_size) {
91
struct net_device *dev;
93
if ((name == NULL) || (setup == NULL)) {
94
return NULL; /* error: invalid args */
97
if (strlen(name) >= ARRAY_SIZE(dev->name)) {
98
return NULL; /* error: name too big */
101
dev = (struct net_device *)pool_alloc(&netdev_pool);
103
return NULL; /* error: no memory */
106
dev->index = index_alloc(&netdev_index, INDEX_NEXT);
108
ret = netdev_init(dev, name, setup, priv_size);
111
return NULL; /* error: see return code */
117
void netdev_free(struct net_device *dev) {
119
dlist_del_init(&dev->rx_lnk);
120
dlist_del_init(&dev->tx_lnk);
121
skb_queue_purge(&dev->dev_queue);
122
skb_queue_purge(&dev->dev_queue_tx);
126
index_free(&netdev_index, dev->index);
127
pool_free(&netdev_pool, dev);
131
int netdev_register(struct net_device *dev) {
132
struct hashtable_item *ht_item;
138
ht_item = pool_alloc(&netdev_htitem_pool);
139
ht_item = hashtable_item_init(ht_item, (void *)&dev->name[0], (void *)dev);
141
return hashtable_put(netdevs_table, ht_item);
144
int netdev_unregister(struct net_device *dev) {
145
struct hashtable_item *ht_item;
150
ht_item = hashtable_del(netdevs_table, (void *)&dev->name[0]);
152
pool_free(&netdev_htitem_pool, ht_item);
158
struct net_device * netdev_get_by_name(const char *name) {
160
return NULL; /* error: invalid name */
163
return hashtable_get(netdevs_table, (void *)name);
166
int netdev_open(struct net_device *dev) {
173
if (dev->flags & IFF_UP) {
177
if (dev->drv_ops != NULL && dev->drv_ops->start != NULL) {
178
ret = dev->drv_ops->start(dev);
184
dev->flags |= IFF_UP;
189
int netdev_close(struct net_device *dev) {
196
if (!(dev->flags & IFF_UP)) {
200
if (dev->drv_ops->stop != NULL) {
201
ret = dev->drv_ops->stop(dev);
207
dev->flags &= ~IFF_UP;
212
int netdev_set_macaddr(struct net_device *dev, const void *addr) {
215
if ((dev == NULL) || (addr == NULL)) {
219
assert(dev->ops != NULL);
220
if ((dev->ops->check_addr != NULL)
221
&& !dev->ops->check_addr(addr)) {
222
return -EINVAL; /* error: bad address */
225
assert(dev->drv_ops != NULL);
226
if (dev->drv_ops->set_macaddr != NULL) {
227
ret = dev->drv_ops->set_macaddr(dev, addr);
233
memcpy(&dev->dev_addr[0], addr, dev->addr_len);
238
int netdev_set_bcastaddr(struct net_device *dev, const void *bcast_addr) {
239
if ((dev == NULL) || (bcast_addr == NULL)) {
243
memcpy(&dev->broadcast[0], bcast_addr, dev->addr_len);
248
int netdev_flag_up(struct net_device *dev, unsigned int flag) {
255
if (dev->flags & flag) {
261
ret = netdev_open(dev);
273
int netdev_flag_down(struct net_device *dev, unsigned int flag) {
280
if (!(dev->flags & flag)) {
286
ret = netdev_close(dev);
298
int netdev_set_mtu(struct net_device *dev, int mtu) {
303
assert(dev->ops != NULL);
304
if ((dev->ops->check_mtu != NULL)
305
&& !dev->ops->check_mtu(mtu)) {
306
return -EINVAL; /* error: bad mtu value */
314
int netdev_set_baseaddr(struct net_device *dev, unsigned long base_addr) {
319
dev->base_addr = base_addr;
324
int netdev_set_irq(struct net_device *dev, int irq_num) {
334
unsigned int if_nametoindex(const char *name) {
335
struct net_device *dev;
339
dev = netdev_get_by_name(name);
349
void netif_carrier_on(struct net_device *dev) {
350
netlink_notify_newlink(dev);
353
void netif_carrier_off(struct net_device *dev) {
354
netlink_notify_dellink(dev);