diff options
author | Julian Wiedmann <jwi@linux.vnet.ibm.com> | 2017-12-13 12:56:32 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-12-15 11:29:43 -0500 |
commit | 02f510f326501470348a5df341e8232c3497bbbb (patch) | |
tree | f50b7623bb50fc8d1d5139e71cb27e15c07c5b25 | |
parent | 8a03a3692b100d84785ee7a834e9215e304c9e00 (diff) |
s390/qeth: update takeover IPs after configuration change
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>
-rw-r--r-- | drivers/s390/net/qeth_core.h | 4 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3.h | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 31 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_sys.c | 63 |
5 files changed, 67 insertions, 37 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 51c618d9fefe..badf42acbf95 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -566,8 +566,8 @@ enum qeth_cq { | |||
566 | 566 | ||
567 | struct qeth_ipato { | 567 | struct qeth_ipato { |
568 | bool enabled; | 568 | bool enabled; |
569 | int invert4; | 569 | bool invert4; |
570 | int invert6; | 570 | bool invert6; |
571 | struct list_head entries; | 571 | struct list_head entries; |
572 | }; | 572 | }; |
573 | 573 | ||
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 8d18675e60e2..6c815207f4f5 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -1481,8 +1481,8 @@ static int qeth_setup_card(struct qeth_card *card) | |||
1481 | /* IP address takeover */ | 1481 | /* IP address takeover */ |
1482 | INIT_LIST_HEAD(&card->ipato.entries); | 1482 | INIT_LIST_HEAD(&card->ipato.entries); |
1483 | card->ipato.enabled = false; | 1483 | card->ipato.enabled = false; |
1484 | card->ipato.invert4 = 0; | 1484 | card->ipato.invert4 = false; |
1485 | card->ipato.invert6 = 0; | 1485 | card->ipato.invert6 = false; |
1486 | /* init QDIO stuff */ | 1486 | /* init QDIO stuff */ |
1487 | qeth_init_qdio_info(card); | 1487 | qeth_init_qdio_info(card); |
1488 | INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work); | 1488 | INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work); |
diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h index 194ae9b577cc..e5833837b799 100644 --- a/drivers/s390/net/qeth_l3.h +++ b/drivers/s390/net/qeth_l3.h | |||
@@ -82,7 +82,7 @@ void qeth_l3_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *); | |||
82 | int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *); | 82 | int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *); |
83 | void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, | 83 | void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, |
84 | const u8 *); | 84 | const u8 *); |
85 | int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *); | 85 | void qeth_l3_update_ipato(struct qeth_card *card); |
86 | struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions); | 86 | struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions); |
87 | int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *); | 87 | int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *); |
88 | int qeth_l3_delete_ip(struct qeth_card *, struct qeth_ipaddr *); | 88 | int qeth_l3_delete_ip(struct qeth_card *, struct qeth_ipaddr *); |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 4a4be81800eb..ef0961e18686 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -164,8 +164,8 @@ static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len) | |||
164 | } | 164 | } |
165 | } | 165 | } |
166 | 166 | ||
167 | int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, | 167 | static bool qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, |
168 | struct qeth_ipaddr *addr) | 168 | struct qeth_ipaddr *addr) |
169 | { | 169 | { |
170 | struct qeth_ipato_entry *ipatoe; | 170 | struct qeth_ipato_entry *ipatoe; |
171 | u8 addr_bits[128] = {0, }; | 171 | u8 addr_bits[128] = {0, }; |
@@ -606,6 +606,27 @@ int qeth_l3_setrouting_v6(struct qeth_card *card) | |||
606 | /* | 606 | /* |
607 | * IP address takeover related functions | 607 | * IP address takeover related functions |
608 | */ | 608 | */ |
609 | |||
610 | /** | ||
611 | * qeth_l3_update_ipato() - Update 'takeover' property, for all NORMAL IPs. | ||
612 | * | ||
613 | * Caller must hold ip_lock. | ||
614 | */ | ||
615 | void qeth_l3_update_ipato(struct qeth_card *card) | ||
616 | { | ||
617 | struct qeth_ipaddr *addr; | ||
618 | unsigned int i; | ||
619 | |||
620 | hash_for_each(card->ip_htable, i, addr, hnode) { | ||
621 | if (addr->type != QETH_IP_TYPE_NORMAL) | ||
622 | continue; | ||
623 | if (qeth_l3_is_addr_covered_by_ipato(card, addr)) | ||
624 | addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG; | ||
625 | else | ||
626 | addr->set_flags &= ~QETH_IPA_SETIP_TAKEOVER_FLAG; | ||
627 | } | ||
628 | } | ||
629 | |||
609 | static void qeth_l3_clear_ipato_list(struct qeth_card *card) | 630 | static void qeth_l3_clear_ipato_list(struct qeth_card *card) |
610 | { | 631 | { |
611 | struct qeth_ipato_entry *ipatoe, *tmp; | 632 | struct qeth_ipato_entry *ipatoe, *tmp; |
@@ -617,6 +638,7 @@ static void qeth_l3_clear_ipato_list(struct qeth_card *card) | |||
617 | kfree(ipatoe); | 638 | kfree(ipatoe); |
618 | } | 639 | } |
619 | 640 | ||
641 | qeth_l3_update_ipato(card); | ||
620 | spin_unlock_bh(&card->ip_lock); | 642 | spin_unlock_bh(&card->ip_lock); |
621 | } | 643 | } |
622 | 644 | ||
@@ -641,8 +663,10 @@ int qeth_l3_add_ipato_entry(struct qeth_card *card, | |||
641 | } | 663 | } |
642 | } | 664 | } |
643 | 665 | ||
644 | if (!rc) | 666 | if (!rc) { |
645 | list_add_tail(&new->entry, &card->ipato.entries); | 667 | list_add_tail(&new->entry, &card->ipato.entries); |
668 | qeth_l3_update_ipato(card); | ||
669 | } | ||
646 | 670 | ||
647 | spin_unlock_bh(&card->ip_lock); | 671 | spin_unlock_bh(&card->ip_lock); |
648 | 672 | ||
@@ -665,6 +689,7 @@ void qeth_l3_del_ipato_entry(struct qeth_card *card, | |||
665 | (proto == QETH_PROT_IPV4)? 4:16) && | 689 | (proto == QETH_PROT_IPV4)? 4:16) && |
666 | (ipatoe->mask_bits == mask_bits)) { | 690 | (ipatoe->mask_bits == mask_bits)) { |
667 | list_del(&ipatoe->entry); | 691 | list_del(&ipatoe->entry); |
692 | qeth_l3_update_ipato(card); | ||
668 | kfree(ipatoe); | 693 | kfree(ipatoe); |
669 | } | 694 | } |
670 | } | 695 | } |
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index aa676b4090da..6ea2b528a64e 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c | |||
@@ -370,9 +370,8 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev, | |||
370 | struct device_attribute *attr, const char *buf, size_t count) | 370 | struct device_attribute *attr, const char *buf, size_t count) |
371 | { | 371 | { |
372 | struct qeth_card *card = dev_get_drvdata(dev); | 372 | struct qeth_card *card = dev_get_drvdata(dev); |
373 | struct qeth_ipaddr *addr; | ||
374 | int i, rc = 0; | ||
375 | bool enable; | 373 | bool enable; |
374 | int rc = 0; | ||
376 | 375 | ||
377 | if (!card) | 376 | if (!card) |
378 | return -EINVAL; | 377 | return -EINVAL; |
@@ -391,20 +390,12 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev, | |||
391 | goto out; | 390 | goto out; |
392 | } | 391 | } |
393 | 392 | ||
394 | if (card->ipato.enabled == enable) | 393 | if (card->ipato.enabled != enable) { |
395 | goto out; | 394 | card->ipato.enabled = enable; |
396 | card->ipato.enabled = enable; | 395 | spin_lock_bh(&card->ip_lock); |
397 | 396 | qeth_l3_update_ipato(card); | |
398 | spin_lock_bh(&card->ip_lock); | 397 | spin_unlock_bh(&card->ip_lock); |
399 | hash_for_each(card->ip_htable, i, addr, hnode) { | ||
400 | if (addr->type != QETH_IP_TYPE_NORMAL) | ||
401 | continue; | ||
402 | if (!enable) | ||
403 | addr->set_flags &= ~QETH_IPA_SETIP_TAKEOVER_FLAG; | ||
404 | else if (qeth_l3_is_addr_covered_by_ipato(card, addr)) | ||
405 | addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG; | ||
406 | } | 398 | } |
407 | spin_unlock_bh(&card->ip_lock); | ||
408 | out: | 399 | out: |
409 | mutex_unlock(&card->conf_mutex); | 400 | mutex_unlock(&card->conf_mutex); |
410 | return rc ? rc : count; | 401 | return rc ? rc : count; |
@@ -430,20 +421,27 @@ static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev, | |||
430 | const char *buf, size_t count) | 421 | const char *buf, size_t count) |
431 | { | 422 | { |
432 | struct qeth_card *card = dev_get_drvdata(dev); | 423 | struct qeth_card *card = dev_get_drvdata(dev); |
424 | bool invert; | ||
433 | int rc = 0; | 425 | int rc = 0; |
434 | 426 | ||
435 | if (!card) | 427 | if (!card) |
436 | return -EINVAL; | 428 | return -EINVAL; |
437 | 429 | ||
438 | mutex_lock(&card->conf_mutex); | 430 | mutex_lock(&card->conf_mutex); |
439 | if (sysfs_streq(buf, "toggle")) | 431 | if (sysfs_streq(buf, "toggle")) { |
440 | card->ipato.invert4 = (card->ipato.invert4)? 0 : 1; | 432 | invert = !card->ipato.invert4; |
441 | else if (sysfs_streq(buf, "1")) | 433 | } else if (kstrtobool(buf, &invert)) { |
442 | card->ipato.invert4 = 1; | ||
443 | else if (sysfs_streq(buf, "0")) | ||
444 | card->ipato.invert4 = 0; | ||
445 | else | ||
446 | rc = -EINVAL; | 434 | rc = -EINVAL; |
435 | goto out; | ||
436 | } | ||
437 | |||
438 | if (card->ipato.invert4 != invert) { | ||
439 | card->ipato.invert4 = invert; | ||
440 | spin_lock_bh(&card->ip_lock); | ||
441 | qeth_l3_update_ipato(card); | ||
442 | spin_unlock_bh(&card->ip_lock); | ||
443 | } | ||
444 | out: | ||
447 | mutex_unlock(&card->conf_mutex); | 445 | mutex_unlock(&card->conf_mutex); |
448 | return rc ? rc : count; | 446 | return rc ? rc : count; |
449 | } | 447 | } |
@@ -609,20 +607,27 @@ static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev, | |||
609 | struct device_attribute *attr, const char *buf, size_t count) | 607 | struct device_attribute *attr, const char *buf, size_t count) |
610 | { | 608 | { |
611 | struct qeth_card *card = dev_get_drvdata(dev); | 609 | struct qeth_card *card = dev_get_drvdata(dev); |
610 | bool invert; | ||
612 | int rc = 0; | 611 | int rc = 0; |
613 | 612 | ||
614 | if (!card) | 613 | if (!card) |
615 | return -EINVAL; | 614 | return -EINVAL; |
616 | 615 | ||
617 | mutex_lock(&card->conf_mutex); | 616 | mutex_lock(&card->conf_mutex); |
618 | if (sysfs_streq(buf, "toggle")) | 617 | if (sysfs_streq(buf, "toggle")) { |
619 | card->ipato.invert6 = (card->ipato.invert6)? 0 : 1; | 618 | invert = !card->ipato.invert6; |
620 | else if (sysfs_streq(buf, "1")) | 619 | } else if (kstrtobool(buf, &invert)) { |
621 | card->ipato.invert6 = 1; | ||
622 | else if (sysfs_streq(buf, "0")) | ||
623 | card->ipato.invert6 = 0; | ||
624 | else | ||
625 | rc = -EINVAL; | 620 | rc = -EINVAL; |
621 | goto out; | ||
622 | } | ||
623 | |||
624 | if (card->ipato.invert6 != invert) { | ||
625 | card->ipato.invert6 = invert; | ||
626 | spin_lock_bh(&card->ip_lock); | ||
627 | qeth_l3_update_ipato(card); | ||
628 | spin_unlock_bh(&card->ip_lock); | ||
629 | } | ||
630 | out: | ||
626 | mutex_unlock(&card->conf_mutex); | 631 | mutex_unlock(&card->conf_mutex); |
627 | return rc ? rc : count; | 632 | return rc ? rc : count; |
628 | } | 633 | } |