Merge branch 'net-x25-netdev-event-handling'
Martin Schiller says: ==================== net/x25: netdev event handling ==================== Link: https://lore.kernel.org/r/20201126063557.1283-1-ms@dev.tdt.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
35c5841889
|
@ -418,14 +418,94 @@ int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb)
|
|||
return used;
|
||||
}
|
||||
|
||||
/* Handle device status changes. */
|
||||
static int lapb_device_event(struct notifier_block *this, unsigned long event,
|
||||
void *ptr)
|
||||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct lapb_cb *lapb;
|
||||
|
||||
if (!net_eq(dev_net(dev), &init_net))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (dev->type != ARPHRD_X25)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
lapb = lapb_devtostruct(dev);
|
||||
if (!lapb)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_UP:
|
||||
lapb_dbg(0, "(%p) Interface up: %s\n", dev, dev->name);
|
||||
|
||||
if (netif_carrier_ok(dev)) {
|
||||
lapb_dbg(0, "(%p): Carrier is already up: %s\n", dev,
|
||||
dev->name);
|
||||
if (lapb->mode & LAPB_DCE) {
|
||||
lapb_start_t1timer(lapb);
|
||||
} else {
|
||||
if (lapb->state == LAPB_STATE_0) {
|
||||
lapb->state = LAPB_STATE_1;
|
||||
lapb_establish_data_link(lapb);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NETDEV_GOING_DOWN:
|
||||
if (netif_carrier_ok(dev))
|
||||
lapb_disconnect_request(dev);
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
lapb_dbg(0, "(%p) Interface down: %s\n", dev, dev->name);
|
||||
lapb_dbg(0, "(%p) S%d -> S0\n", dev, lapb->state);
|
||||
lapb_clear_queues(lapb);
|
||||
lapb->state = LAPB_STATE_0;
|
||||
lapb->n2count = 0;
|
||||
lapb_stop_t1timer(lapb);
|
||||
lapb_stop_t2timer(lapb);
|
||||
break;
|
||||
case NETDEV_CHANGE:
|
||||
if (netif_carrier_ok(dev)) {
|
||||
lapb_dbg(0, "(%p): Carrier detected: %s\n", dev,
|
||||
dev->name);
|
||||
if (lapb->mode & LAPB_DCE) {
|
||||
lapb_start_t1timer(lapb);
|
||||
} else {
|
||||
if (lapb->state == LAPB_STATE_0) {
|
||||
lapb->state = LAPB_STATE_1;
|
||||
lapb_establish_data_link(lapb);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lapb_dbg(0, "(%p) Carrier lost: %s\n", dev, dev->name);
|
||||
lapb_dbg(0, "(%p) S%d -> S0\n", dev, lapb->state);
|
||||
lapb_clear_queues(lapb);
|
||||
lapb->state = LAPB_STATE_0;
|
||||
lapb->n2count = 0;
|
||||
lapb_stop_t1timer(lapb);
|
||||
lapb_stop_t2timer(lapb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block lapb_dev_notifier = {
|
||||
.notifier_call = lapb_device_event,
|
||||
};
|
||||
|
||||
static int __init lapb_init(void)
|
||||
{
|
||||
return 0;
|
||||
return register_netdevice_notifier(&lapb_dev_notifier);
|
||||
}
|
||||
|
||||
static void __exit lapb_exit(void)
|
||||
{
|
||||
WARN_ON(!list_empty(&lapb_list));
|
||||
|
||||
unregister_netdevice_notifier(&lapb_dev_notifier);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
|
||||
|
|
|
@ -85,11 +85,18 @@ static void lapb_t1timer_expiry(struct timer_list *t)
|
|||
switch (lapb->state) {
|
||||
|
||||
/*
|
||||
* If we are a DCE, keep going DM .. DM .. DM
|
||||
* If we are a DCE, send DM up to N2 times, then switch to
|
||||
* STATE_1 and send SABM(E).
|
||||
*/
|
||||
case LAPB_STATE_0:
|
||||
if (lapb->mode & LAPB_DCE)
|
||||
if (lapb->mode & LAPB_DCE &&
|
||||
lapb->n2count != lapb->n2) {
|
||||
lapb->n2count++;
|
||||
lapb_send_control(lapb, LAPB_DM, LAPB_POLLOFF, LAPB_RESPONSE);
|
||||
} else {
|
||||
lapb->state = LAPB_STATE_1;
|
||||
lapb_establish_data_link(lapb);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
|
|
|
@ -199,22 +199,6 @@ static void x25_remove_socket(struct sock *sk)
|
|||
write_unlock_bh(&x25_list_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Kill all bound sockets on a dropped device.
|
||||
*/
|
||||
static void x25_kill_by_device(struct net_device *dev)
|
||||
{
|
||||
struct sock *s;
|
||||
|
||||
write_lock_bh(&x25_list_lock);
|
||||
|
||||
sk_for_each(s, &x25_list)
|
||||
if (x25_sk(s)->neighbour && x25_sk(s)->neighbour->dev == dev)
|
||||
x25_disconnect(s, ENETUNREACH, 0, 0);
|
||||
|
||||
write_unlock_bh(&x25_list_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle device status changes.
|
||||
*/
|
||||
|
@ -233,21 +217,31 @@ static int x25_device_event(struct notifier_block *this, unsigned long event,
|
|||
#endif
|
||||
) {
|
||||
switch (event) {
|
||||
case NETDEV_UP:
|
||||
case NETDEV_REGISTER:
|
||||
case NETDEV_POST_TYPE_CHANGE:
|
||||
x25_link_device_up(dev);
|
||||
break;
|
||||
case NETDEV_GOING_DOWN:
|
||||
case NETDEV_DOWN:
|
||||
nb = x25_get_neigh(dev);
|
||||
if (nb) {
|
||||
x25_terminate_link(nb);
|
||||
x25_link_terminated(nb);
|
||||
x25_neigh_put(nb);
|
||||
}
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
x25_kill_by_device(dev);
|
||||
x25_route_device_down(dev);
|
||||
break;
|
||||
case NETDEV_PRE_TYPE_CHANGE:
|
||||
case NETDEV_UNREGISTER:
|
||||
x25_link_device_down(dev);
|
||||
break;
|
||||
case NETDEV_CHANGE:
|
||||
if (!netif_carrier_ok(dev)) {
|
||||
nb = x25_get_neigh(dev);
|
||||
if (nb) {
|
||||
x25_link_terminated(nb);
|
||||
x25_neigh_put(nb);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,16 +74,43 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *nb,
|
|||
|
||||
switch (frametype) {
|
||||
case X25_RESTART_REQUEST:
|
||||
confirm = !x25_t20timer_pending(nb);
|
||||
x25_stop_t20timer(nb);
|
||||
nb->state = X25_LINK_STATE_3;
|
||||
if (confirm)
|
||||
switch (nb->state) {
|
||||
case X25_LINK_STATE_2:
|
||||
confirm = !x25_t20timer_pending(nb);
|
||||
x25_stop_t20timer(nb);
|
||||
nb->state = X25_LINK_STATE_3;
|
||||
if (confirm)
|
||||
x25_transmit_restart_confirmation(nb);
|
||||
break;
|
||||
case X25_LINK_STATE_3:
|
||||
/* clear existing virtual calls */
|
||||
x25_kill_by_neigh(nb);
|
||||
|
||||
x25_transmit_restart_confirmation(nb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case X25_RESTART_CONFIRMATION:
|
||||
x25_stop_t20timer(nb);
|
||||
nb->state = X25_LINK_STATE_3;
|
||||
switch (nb->state) {
|
||||
case X25_LINK_STATE_2:
|
||||
if (x25_t20timer_pending(nb)) {
|
||||
x25_stop_t20timer(nb);
|
||||
nb->state = X25_LINK_STATE_3;
|
||||
} else {
|
||||
x25_transmit_restart_request(nb);
|
||||
x25_start_t20timer(nb);
|
||||
}
|
||||
break;
|
||||
case X25_LINK_STATE_3:
|
||||
/* clear existing virtual calls */
|
||||
x25_kill_by_neigh(nb);
|
||||
|
||||
x25_transmit_restart_request(nb);
|
||||
nb->state = X25_LINK_STATE_2;
|
||||
x25_start_t20timer(nb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case X25_DIAGNOSTIC:
|
||||
|
@ -214,8 +241,6 @@ void x25_link_established(struct x25_neigh *nb)
|
|||
{
|
||||
switch (nb->state) {
|
||||
case X25_LINK_STATE_0:
|
||||
nb->state = X25_LINK_STATE_2;
|
||||
break;
|
||||
case X25_LINK_STATE_1:
|
||||
x25_transmit_restart_request(nb);
|
||||
nb->state = X25_LINK_STATE_2;
|
||||
|
@ -232,6 +257,9 @@ void x25_link_established(struct x25_neigh *nb)
|
|||
void x25_link_terminated(struct x25_neigh *nb)
|
||||
{
|
||||
nb->state = X25_LINK_STATE_0;
|
||||
skb_queue_purge(&nb->queue);
|
||||
x25_stop_t20timer(nb);
|
||||
|
||||
/* Out of order: clear existing virtual calls (X.25 03/93 4.6.3) */
|
||||
x25_kill_by_neigh(nb);
|
||||
}
|
||||
|
@ -277,9 +305,6 @@ void x25_link_device_up(struct net_device *dev)
|
|||
*/
|
||||
static void __x25_remove_neigh(struct x25_neigh *nb)
|
||||
{
|
||||
skb_queue_purge(&nb->queue);
|
||||
x25_stop_t20timer(nb);
|
||||
|
||||
if (nb->node.next) {
|
||||
list_del(&nb->node);
|
||||
x25_neigh_put(nb);
|
||||
|
|
|
@ -115,9 +115,6 @@ void x25_route_device_down(struct net_device *dev)
|
|||
__x25_remove_route(rt);
|
||||
}
|
||||
write_unlock_bh(&x25_route_list_lock);
|
||||
|
||||
/* Remove any related forwarding */
|
||||
x25_clear_forward_by_dev(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue