net: l2: Add enable callback

This adds enable callback which can be used to notify the L2 driver about
changes of interface state, the L2 driver can then check if the new state
is allowed and reject otherwise.

Change-Id: I4bb6b1e32be2633f24694c0246585f803f8c645d
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz 2016-12-21 13:33:09 +02:00 committed by Tomasz Bursztyka
commit 8a16c6681a
6 changed files with 54 additions and 5 deletions

View file

@ -55,6 +55,12 @@ struct net_l2 {
*/ */
uint16_t (*reserve)(struct net_if *iface, void *data); uint16_t (*reserve)(struct net_if *iface, void *data);
/**
* This function is used to enable/disable traffic over a network
* interface.
*/
int (*enable)(struct net_if *iface, bool state);
#if defined(CONFIG_NET_L2_OFFLOAD_IP) #if defined(CONFIG_NET_L2_OFFLOAD_IP)
struct net_l2_offload_ip *offload_ip; struct net_l2_offload_ip *offload_ip;
#endif /* CONFIG_NET_L2_OFFLOAD_IP */ #endif /* CONFIG_NET_L2_OFFLOAD_IP */
@ -98,12 +104,13 @@ NET_L2_DECLARE_PUBLIC(IEEE802154_L2);
extern struct net_l2 __net_l2_end[]; extern struct net_l2 __net_l2_end[];
#define NET_L2_INIT(_name, _recv_fn, _send_fn, _reserve_fn) \ #define NET_L2_INIT(_name, _recv_fn, _send_fn, _reserve_fn, _enable_fn) \
const struct net_l2 const (NET_L2_GET_NAME(_name)) __used \ const struct net_l2 const (NET_L2_GET_NAME(_name)) __used \
__attribute__((__section__(".net_l2.init"))) = { \ __attribute__((__section__(".net_l2.init"))) = { \
.recv = (_recv_fn), \ .recv = (_recv_fn), \
.send = (_send_fn), \ .send = (_send_fn), \
.reserve = (_reserve_fn), \ .reserve = (_reserve_fn), \
.enable = (_enable_fn), \
} }
#define NET_L2_GET_DATA(name, sfx) (__net_l2_data_##name##sfx) #define NET_L2_GET_DATA(name, sfx) (__net_l2_data_##name##sfx)

View file

@ -109,7 +109,21 @@ static inline uint16_t net_bt_reserve(struct net_if *iface, void *unused)
return 0; return 0;
} }
NET_L2_INIT(BLUETOOTH_L2, net_bt_recv, net_bt_send, net_bt_reserve); static int net_bt_enable(struct net_if *iface, bool state)
{
struct bt_context *ctxt = net_if_get_device(iface)->driver_data;
NET_DBG("iface %p %s", iface, state ? "up" : "down");
if (state && !ctxt->ipsp_chan.chan.conn) {
return -ENETDOWN;
}
return 0;
}
NET_L2_INIT(BLUETOOTH_L2, net_bt_recv, net_bt_send, net_bt_reserve,
net_bt_enable);
static void ipsp_connected(struct bt_l2cap_chan *chan) static void ipsp_connected(struct bt_l2cap_chan *chan)
{ {

View file

@ -46,4 +46,4 @@ static inline uint16_t dummy_reserve(struct net_if *iface, void *unused)
return 0; return 0;
} }
NET_L2_INIT(DUMMY_L2, dummy_recv, dummy_send, dummy_reserve); NET_L2_INIT(DUMMY_L2, dummy_recv, dummy_send, dummy_reserve, NULL);

View file

@ -343,4 +343,4 @@ static inline uint16_t ethernet_reserve(struct net_if *iface, void *unused)
return sizeof(struct net_eth_hdr); return sizeof(struct net_eth_hdr);
} }
NET_L2_INIT(ETHERNET_L2, ethernet_recv, ethernet_send, ethernet_reserve); NET_L2_INIT(ETHERNET_L2, ethernet_recv, ethernet_send, ethernet_reserve, NULL);

View file

@ -321,7 +321,7 @@ static uint16_t ieeee802154_reserve(struct net_if *iface, void *data)
} }
NET_L2_INIT(IEEE802154_L2, NET_L2_INIT(IEEE802154_L2,
ieee802154_recv, ieee802154_send, ieeee802154_reserve); ieee802154_recv, ieee802154_send, ieeee802154_reserve, NULL);
void ieee802154_init(struct net_if *iface) void ieee802154_init(struct net_if *iface)
{ {

View file

@ -1343,12 +1343,26 @@ void net_if_foreach(net_if_cb_t cb, void *user_data)
int net_if_up(struct net_if *iface) int net_if_up(struct net_if *iface)
{ {
int status;
NET_DBG("iface %p", iface); NET_DBG("iface %p", iface);
if (atomic_test_bit(iface->flags, NET_IF_UP)) { if (atomic_test_bit(iface->flags, NET_IF_UP)) {
return 0; return 0;
} }
/* If the L2 does not support enable just set the flag */
if (!iface->l2->enable) {
goto done;
}
/* Notify L2 to enable the interface */
status = iface->l2->enable(iface, true);
if (status < 0) {
return status;
}
done:
atomic_set_bit(iface->flags, NET_IF_UP); atomic_set_bit(iface->flags, NET_IF_UP);
#if defined(CONFIG_NET_IPV6_DAD) #if defined(CONFIG_NET_IPV6_DAD)
@ -1366,8 +1380,22 @@ int net_if_up(struct net_if *iface)
int net_if_down(struct net_if *iface) int net_if_down(struct net_if *iface)
{ {
int status;
NET_DBG("iface %p", iface); NET_DBG("iface %p", iface);
/* If the L2 does not support enable just set the flag */
if (!iface->l2->enable) {
goto done;
}
/* Notify L2 to disable the interface */
status = iface->l2->enable(iface, false);
if (status < 0) {
return status;
}
done:
atomic_clear_bit(iface->flags, NET_IF_UP); atomic_clear_bit(iface->flags, NET_IF_UP);
return 0; return 0;