Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

qeth: IFF_PROMISC flag to BRIDGE PORT mode

OSA and HiperSocket devices do not support promiscuous mode proper,
but they support "BRIDGE PORT" mode that is functionally similar.
This update introduces sysfs attribute that, when set, makes the driver
try to "reflect" setting and resetting of the IFF_PROMISC flag on the
interface into setting and resetting PRIMARY or SECONDARY bridge port
role on the underlying OSA or HiperSocket device.

Reviewed-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Signed-off-by: Eugene Crosser <Eugene.Crosser@ru.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eugene Crosser and committed by
David S. Miller
0db587b0 d3c29a5c

+95 -3
+2
drivers/s390/net/qeth_core.h
··· 175 175 __u32 supported_funcs; 176 176 enum qeth_sbp_roles role; 177 177 __u32 hostnotification:1; 178 + __u32 reflect_promisc:1; 179 + __u32 reflect_promisc_primary:1; 178 180 }; 179 181 180 182 static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa,
+37 -3
drivers/s390/net/qeth_l2_main.c
··· 683 683 return rc ? -EINVAL : 0; 684 684 } 685 685 686 + static void qeth_promisc_to_bridge(struct qeth_card *card) 687 + { 688 + struct net_device *dev = card->dev; 689 + enum qeth_ipa_promisc_modes promisc_mode; 690 + int role; 691 + int rc; 692 + 693 + QETH_CARD_TEXT(card, 3, "pmisc2br"); 694 + 695 + if (!card->options.sbp.reflect_promisc) 696 + return; 697 + promisc_mode = (dev->flags & IFF_PROMISC) ? SET_PROMISC_MODE_ON 698 + : SET_PROMISC_MODE_OFF; 699 + if (promisc_mode == card->info.promisc_mode) 700 + return; 701 + 702 + if (promisc_mode == SET_PROMISC_MODE_ON) { 703 + if (card->options.sbp.reflect_promisc_primary) 704 + role = QETH_SBP_ROLE_PRIMARY; 705 + else 706 + role = QETH_SBP_ROLE_SECONDARY; 707 + } else 708 + role = QETH_SBP_ROLE_NONE; 709 + 710 + rc = qeth_bridgeport_setrole(card, role); 711 + QETH_DBF_TEXT_(SETUP, 2, "bpm%c%04x", 712 + (promisc_mode == SET_PROMISC_MODE_ON) ? '+' : '-', rc); 713 + if (!rc) { 714 + card->options.sbp.role = role; 715 + card->info.promisc_mode = promisc_mode; 716 + } 717 + } 718 + 686 719 static void qeth_l2_set_multicast_list(struct net_device *dev) 687 720 { 688 721 struct qeth_card *card = dev->ml_priv; ··· 737 704 qeth_l2_add_mc(card, ha->addr, 1); 738 705 739 706 spin_unlock_bh(&card->mclock); 740 - if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) 741 - return; 742 - qeth_setadp_promisc_mode(card); 707 + if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) 708 + qeth_setadp_promisc_mode(card); 709 + else 710 + qeth_promisc_to_bridge(card); 743 711 } 744 712 745 713 static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+56
drivers/s390/net/qeth_l2_sys.c
··· 159 159 qeth_bridgeport_hostnotification_show, 160 160 qeth_bridgeport_hostnotification_store); 161 161 162 + static ssize_t qeth_bridgeport_reflect_show(struct device *dev, 163 + struct device_attribute *attr, char *buf) 164 + { 165 + struct qeth_card *card = dev_get_drvdata(dev); 166 + char *state; 167 + 168 + if (!card) 169 + return -EINVAL; 170 + 171 + if (card->options.sbp.reflect_promisc) { 172 + if (card->options.sbp.reflect_promisc_primary) 173 + state = "primary"; 174 + else 175 + state = "secondary"; 176 + } else 177 + state = "none"; 178 + 179 + return sprintf(buf, "%s\n", state); 180 + } 181 + 182 + static ssize_t qeth_bridgeport_reflect_store(struct device *dev, 183 + struct device_attribute *attr, const char *buf, size_t count) 184 + { 185 + struct qeth_card *card = dev_get_drvdata(dev); 186 + int enable, primary; 187 + 188 + if (!card) 189 + return -EINVAL; 190 + 191 + if (sysfs_streq(buf, "none")) { 192 + enable = 0; 193 + primary = 0; 194 + } else if (sysfs_streq(buf, "primary")) { 195 + enable = 1; 196 + primary = 1; 197 + } else if (sysfs_streq(buf, "secondary")) { 198 + enable = 1; 199 + primary = 0; 200 + } else 201 + return -EINVAL; 202 + 203 + mutex_lock(&card->conf_mutex); 204 + 205 + card->options.sbp.reflect_promisc = enable; 206 + card->options.sbp.reflect_promisc_primary = primary; 207 + 208 + mutex_unlock(&card->conf_mutex); 209 + 210 + return count; 211 + } 212 + 213 + static DEVICE_ATTR(bridge_reflect_promisc, 0644, 214 + qeth_bridgeport_reflect_show, 215 + qeth_bridgeport_reflect_store); 216 + 162 217 static struct attribute *qeth_l2_bridgeport_attrs[] = { 163 218 &dev_attr_bridge_role.attr, 164 219 &dev_attr_bridge_state.attr, 165 220 &dev_attr_bridge_hostnotify.attr, 221 + &dev_attr_bridge_reflect_promisc.attr, 166 222 NULL, 167 223 }; 168 224