Commit 35c58418 authored by Jakub Kicinski's avatar Jakub Kicinski

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.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents f5d709ff 139d6eb1
...@@ -418,14 +418,94 @@ int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb) ...@@ -418,14 +418,94 @@ int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb)
return used; 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) static int __init lapb_init(void)
{ {
return 0; return register_netdevice_notifier(&lapb_dev_notifier);
} }
static void __exit lapb_exit(void) static void __exit lapb_exit(void)
{ {
WARN_ON(!list_empty(&lapb_list)); WARN_ON(!list_empty(&lapb_list));
unregister_netdevice_notifier(&lapb_dev_notifier);
} }
MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>"); MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
......
...@@ -85,11 +85,18 @@ static void lapb_t1timer_expiry(struct timer_list *t) ...@@ -85,11 +85,18 @@ static void lapb_t1timer_expiry(struct timer_list *t)
switch (lapb->state) { 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: 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); lapb_send_control(lapb, LAPB_DM, LAPB_POLLOFF, LAPB_RESPONSE);
} else {
lapb->state = LAPB_STATE_1;
lapb_establish_data_link(lapb);
}
break; break;
/* /*
......
...@@ -199,22 +199,6 @@ static void x25_remove_socket(struct sock *sk) ...@@ -199,22 +199,6 @@ static void x25_remove_socket(struct sock *sk)
write_unlock_bh(&x25_list_lock); 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. * Handle device status changes.
*/ */
...@@ -233,21 +217,31 @@ static int x25_device_event(struct notifier_block *this, unsigned long event, ...@@ -233,21 +217,31 @@ static int x25_device_event(struct notifier_block *this, unsigned long event,
#endif #endif
) { ) {
switch (event) { switch (event) {
case NETDEV_UP: case NETDEV_REGISTER:
case NETDEV_POST_TYPE_CHANGE:
x25_link_device_up(dev); x25_link_device_up(dev);
break; break;
case NETDEV_GOING_DOWN: case NETDEV_DOWN:
nb = x25_get_neigh(dev); nb = x25_get_neigh(dev);
if (nb) { if (nb) {
x25_terminate_link(nb); x25_link_terminated(nb);
x25_neigh_put(nb); x25_neigh_put(nb);
} }
break;
case NETDEV_DOWN:
x25_kill_by_device(dev);
x25_route_device_down(dev); x25_route_device_down(dev);
break;
case NETDEV_PRE_TYPE_CHANGE:
case NETDEV_UNREGISTER:
x25_link_device_down(dev); x25_link_device_down(dev);
break; 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, ...@@ -74,16 +74,43 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *nb,
switch (frametype) { switch (frametype) {
case X25_RESTART_REQUEST: case X25_RESTART_REQUEST:
confirm = !x25_t20timer_pending(nb); switch (nb->state) {
x25_stop_t20timer(nb); case X25_LINK_STATE_2:
nb->state = X25_LINK_STATE_3; confirm = !x25_t20timer_pending(nb);
if (confirm) 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); x25_transmit_restart_confirmation(nb);
break;
}
break; break;
case X25_RESTART_CONFIRMATION: case X25_RESTART_CONFIRMATION:
x25_stop_t20timer(nb); switch (nb->state) {
nb->state = X25_LINK_STATE_3; 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; break;
case X25_DIAGNOSTIC: case X25_DIAGNOSTIC:
...@@ -214,8 +241,6 @@ void x25_link_established(struct x25_neigh *nb) ...@@ -214,8 +241,6 @@ void x25_link_established(struct x25_neigh *nb)
{ {
switch (nb->state) { switch (nb->state) {
case X25_LINK_STATE_0: case X25_LINK_STATE_0:
nb->state = X25_LINK_STATE_2;
break;
case X25_LINK_STATE_1: case X25_LINK_STATE_1:
x25_transmit_restart_request(nb); x25_transmit_restart_request(nb);
nb->state = X25_LINK_STATE_2; nb->state = X25_LINK_STATE_2;
...@@ -232,6 +257,9 @@ void x25_link_established(struct x25_neigh *nb) ...@@ -232,6 +257,9 @@ void x25_link_established(struct x25_neigh *nb)
void x25_link_terminated(struct x25_neigh *nb) void x25_link_terminated(struct x25_neigh *nb)
{ {
nb->state = X25_LINK_STATE_0; 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) */ /* Out of order: clear existing virtual calls (X.25 03/93 4.6.3) */
x25_kill_by_neigh(nb); x25_kill_by_neigh(nb);
} }
...@@ -277,9 +305,6 @@ void x25_link_device_up(struct net_device *dev) ...@@ -277,9 +305,6 @@ void x25_link_device_up(struct net_device *dev)
*/ */
static void __x25_remove_neigh(struct x25_neigh *nb) static void __x25_remove_neigh(struct x25_neigh *nb)
{ {
skb_queue_purge(&nb->queue);
x25_stop_t20timer(nb);
if (nb->node.next) { if (nb->node.next) {
list_del(&nb->node); list_del(&nb->node);
x25_neigh_put(nb); x25_neigh_put(nb);
......
...@@ -115,9 +115,6 @@ void x25_route_device_down(struct net_device *dev) ...@@ -115,9 +115,6 @@ void x25_route_device_down(struct net_device *dev)
__x25_remove_route(rt); __x25_remove_route(rt);
} }
write_unlock_bh(&x25_route_list_lock); write_unlock_bh(&x25_route_list_lock);
/* Remove any related forwarding */
x25_clear_forward_by_dev(dev);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment