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)
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);
}
/*
......
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