aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulian Wiedmann <jwi@linux.vnet.ibm.com>2017-12-13 12:56:32 -0500
committerDavid S. Miller <davem@davemloft.net>2017-12-15 11:29:43 -0500
commit02f510f326501470348a5df341e8232c3497bbbb (patch)
treef50b7623bb50fc8d1d5139e71cb27e15c07c5b25
parent8a03a3692b100d84785ee7a834e9215e304c9e00 (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.h4
-rw-r--r--drivers/s390/net/qeth_core_main.c4
-rw-r--r--drivers/s390/net/qeth_l3.h2
-rw-r--r--drivers/s390/net/qeth_l3_main.c31
-rw-r--r--drivers/s390/net/qeth_l3_sys.c63
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
567struct qeth_ipato { 567struct 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 *);
82int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *); 82int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
83void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, 83void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
84 const u8 *); 84 const u8 *);
85int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *); 85void qeth_l3_update_ipato(struct qeth_card *card);
86struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions); 86struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions);
87int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *); 87int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *);
88int qeth_l3_delete_ip(struct qeth_card *, struct qeth_ipaddr *); 88int 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
167int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, 167static 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 */
615void 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
609static void qeth_l3_clear_ipato_list(struct qeth_card *card) 630static 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);
408out: 399out:
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 }
444out:
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 }
630out:
626 mutex_unlock(&card->conf_mutex); 631 mutex_unlock(&card->conf_mutex);
627 return rc ? rc : count; 632 return rc ? rc : count;
628} 633}