| From foo@baz Sun Dec 31 11:13:15 CET 2017 |
| From: Julian Wiedmann <jwi@linux.vnet.ibm.com> |
| Date: Wed, 13 Dec 2017 18:56:32 +0100 |
| Subject: s390/qeth: update takeover IPs after configuration change |
| |
| From: Julian Wiedmann <jwi@linux.vnet.ibm.com> |
| |
| |
| [ Upstream commit 02f510f326501470348a5df341e8232c3497bbbb ] |
| |
| Any modification to the takeover IP-ranges requires that we re-evaluate |
| which IP addresses are takeover-eligible. Otherwise we might do takeover |
| for some addresses when we no longer should, or vice-versa. |
| |
| Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/s390/net/qeth_core.h | 4 +- |
| drivers/s390/net/qeth_core_main.c | 4 +- |
| drivers/s390/net/qeth_l3.h | 2 - |
| drivers/s390/net/qeth_l3_main.c | 31 ++++++++++++++++-- |
| drivers/s390/net/qeth_l3_sys.c | 63 ++++++++++++++++++++------------------ |
| 5 files changed, 67 insertions(+), 37 deletions(-) |
| |
| --- a/drivers/s390/net/qeth_core.h |
| +++ b/drivers/s390/net/qeth_core.h |
| @@ -577,8 +577,8 @@ enum qeth_cq { |
| |
| struct qeth_ipato { |
| bool enabled; |
| - int invert4; |
| - int invert6; |
| + bool invert4; |
| + bool invert6; |
| struct list_head entries; |
| }; |
| |
| --- a/drivers/s390/net/qeth_core_main.c |
| +++ b/drivers/s390/net/qeth_core_main.c |
| @@ -1476,8 +1476,8 @@ static int qeth_setup_card(struct qeth_c |
| /* IP address takeover */ |
| INIT_LIST_HEAD(&card->ipato.entries); |
| card->ipato.enabled = false; |
| - card->ipato.invert4 = 0; |
| - card->ipato.invert6 = 0; |
| + card->ipato.invert4 = false; |
| + card->ipato.invert6 = false; |
| /* init QDIO stuff */ |
| qeth_init_qdio_info(card); |
| INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work); |
| --- a/drivers/s390/net/qeth_l3.h |
| +++ b/drivers/s390/net/qeth_l3.h |
| @@ -80,7 +80,7 @@ void qeth_l3_del_vipa(struct qeth_card * |
| int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *); |
| void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, |
| const u8 *); |
| -int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *); |
| +void qeth_l3_update_ipato(struct qeth_card *card); |
| struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions); |
| int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *); |
| int qeth_l3_delete_ip(struct qeth_card *, struct qeth_ipaddr *); |
| --- a/drivers/s390/net/qeth_l3_main.c |
| +++ b/drivers/s390/net/qeth_l3_main.c |
| @@ -168,8 +168,8 @@ static void qeth_l3_convert_addr_to_bits |
| } |
| } |
| |
| -int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, |
| - struct qeth_ipaddr *addr) |
| +static bool qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, |
| + struct qeth_ipaddr *addr) |
| { |
| struct qeth_ipato_entry *ipatoe; |
| u8 addr_bits[128] = {0, }; |
| @@ -608,6 +608,27 @@ int qeth_l3_setrouting_v6(struct qeth_ca |
| /* |
| * IP address takeover related functions |
| */ |
| + |
| +/** |
| + * qeth_l3_update_ipato() - Update 'takeover' property, for all NORMAL IPs. |
| + * |
| + * Caller must hold ip_lock. |
| + */ |
| +void qeth_l3_update_ipato(struct qeth_card *card) |
| +{ |
| + struct qeth_ipaddr *addr; |
| + unsigned int i; |
| + |
| + hash_for_each(card->ip_htable, i, addr, hnode) { |
| + if (addr->type != QETH_IP_TYPE_NORMAL) |
| + continue; |
| + if (qeth_l3_is_addr_covered_by_ipato(card, addr)) |
| + addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG; |
| + else |
| + addr->set_flags &= ~QETH_IPA_SETIP_TAKEOVER_FLAG; |
| + } |
| +} |
| + |
| static void qeth_l3_clear_ipato_list(struct qeth_card *card) |
| { |
| struct qeth_ipato_entry *ipatoe, *tmp; |
| @@ -619,6 +640,7 @@ static void qeth_l3_clear_ipato_list(str |
| kfree(ipatoe); |
| } |
| |
| + qeth_l3_update_ipato(card); |
| spin_unlock_bh(&card->ip_lock); |
| } |
| |
| @@ -643,8 +665,10 @@ int qeth_l3_add_ipato_entry(struct qeth_ |
| } |
| } |
| |
| - if (!rc) |
| + if (!rc) { |
| list_add_tail(&new->entry, &card->ipato.entries); |
| + qeth_l3_update_ipato(card); |
| + } |
| |
| spin_unlock_bh(&card->ip_lock); |
| |
| @@ -667,6 +691,7 @@ void qeth_l3_del_ipato_entry(struct qeth |
| (proto == QETH_PROT_IPV4)? 4:16) && |
| (ipatoe->mask_bits == mask_bits)) { |
| list_del(&ipatoe->entry); |
| + qeth_l3_update_ipato(card); |
| kfree(ipatoe); |
| } |
| } |
| --- a/drivers/s390/net/qeth_l3_sys.c |
| +++ b/drivers/s390/net/qeth_l3_sys.c |
| @@ -372,9 +372,8 @@ static ssize_t qeth_l3_dev_ipato_enable_ |
| struct device_attribute *attr, const char *buf, size_t count) |
| { |
| struct qeth_card *card = dev_get_drvdata(dev); |
| - struct qeth_ipaddr *addr; |
| - int i, rc = 0; |
| bool enable; |
| + int rc = 0; |
| |
| if (!card) |
| return -EINVAL; |
| @@ -393,20 +392,12 @@ static ssize_t qeth_l3_dev_ipato_enable_ |
| goto out; |
| } |
| |
| - if (card->ipato.enabled == enable) |
| - goto out; |
| - card->ipato.enabled = enable; |
| - |
| - spin_lock_bh(&card->ip_lock); |
| - hash_for_each(card->ip_htable, i, addr, hnode) { |
| - if (addr->type != QETH_IP_TYPE_NORMAL) |
| - continue; |
| - if (!enable) |
| - addr->set_flags &= ~QETH_IPA_SETIP_TAKEOVER_FLAG; |
| - else if (qeth_l3_is_addr_covered_by_ipato(card, addr)) |
| - addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG; |
| + if (card->ipato.enabled != enable) { |
| + card->ipato.enabled = enable; |
| + spin_lock_bh(&card->ip_lock); |
| + qeth_l3_update_ipato(card); |
| + spin_unlock_bh(&card->ip_lock); |
| } |
| - spin_unlock_bh(&card->ip_lock); |
| out: |
| mutex_unlock(&card->conf_mutex); |
| return rc ? rc : count; |
| @@ -432,20 +423,27 @@ static ssize_t qeth_l3_dev_ipato_invert4 |
| const char *buf, size_t count) |
| { |
| struct qeth_card *card = dev_get_drvdata(dev); |
| + bool invert; |
| int rc = 0; |
| |
| if (!card) |
| return -EINVAL; |
| |
| mutex_lock(&card->conf_mutex); |
| - if (sysfs_streq(buf, "toggle")) |
| - card->ipato.invert4 = (card->ipato.invert4)? 0 : 1; |
| - else if (sysfs_streq(buf, "1")) |
| - card->ipato.invert4 = 1; |
| - else if (sysfs_streq(buf, "0")) |
| - card->ipato.invert4 = 0; |
| - else |
| + if (sysfs_streq(buf, "toggle")) { |
| + invert = !card->ipato.invert4; |
| + } else if (kstrtobool(buf, &invert)) { |
| rc = -EINVAL; |
| + goto out; |
| + } |
| + |
| + if (card->ipato.invert4 != invert) { |
| + card->ipato.invert4 = invert; |
| + spin_lock_bh(&card->ip_lock); |
| + qeth_l3_update_ipato(card); |
| + spin_unlock_bh(&card->ip_lock); |
| + } |
| +out: |
| mutex_unlock(&card->conf_mutex); |
| return rc ? rc : count; |
| } |
| @@ -611,20 +609,27 @@ static ssize_t qeth_l3_dev_ipato_invert6 |
| struct device_attribute *attr, const char *buf, size_t count) |
| { |
| struct qeth_card *card = dev_get_drvdata(dev); |
| + bool invert; |
| int rc = 0; |
| |
| if (!card) |
| return -EINVAL; |
| |
| mutex_lock(&card->conf_mutex); |
| - if (sysfs_streq(buf, "toggle")) |
| - card->ipato.invert6 = (card->ipato.invert6)? 0 : 1; |
| - else if (sysfs_streq(buf, "1")) |
| - card->ipato.invert6 = 1; |
| - else if (sysfs_streq(buf, "0")) |
| - card->ipato.invert6 = 0; |
| - else |
| + if (sysfs_streq(buf, "toggle")) { |
| + invert = !card->ipato.invert6; |
| + } else if (kstrtobool(buf, &invert)) { |
| rc = -EINVAL; |
| + goto out; |
| + } |
| + |
| + if (card->ipato.invert6 != invert) { |
| + card->ipato.invert6 = invert; |
| + spin_lock_bh(&card->ip_lock); |
| + qeth_l3_update_ipato(card); |
| + spin_unlock_bh(&card->ip_lock); |
| + } |
| +out: |
| mutex_unlock(&card->conf_mutex); |
| return rc ? rc : count; |
| } |