aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_l3_main.c
diff options
context:
space:
mode:
authorUrsula Braun <ursula.braun@de.ibm.com>2010-01-10 21:50:50 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-13 23:34:55 -0500
commit76b11f8e270f04851774ff64b16e29e5a43d3a1a (patch)
treed4e7666c766bd1fba5ef2219717f302faf3a21bf /drivers/s390/net/qeth_l3_main.c
parentab8932f3e8e07df92d6ce3fa41f5af0dda865429 (diff)
qeth: HiperSockets Network Traffic Analyzer
New feature to trace HiperSockets network traffic for debugging purposes. Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390/net/qeth_l3_main.c')
-rw-r--r--drivers/s390/net/qeth_l3_main.c174
1 files changed, 150 insertions, 24 deletions
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index fd1b6ed3721f..337d03fb045d 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -242,6 +242,8 @@ static int __qeth_l3_insert_ip_todo(struct qeth_card *card,
242 struct qeth_ipaddr *tmp, *t; 242 struct qeth_ipaddr *tmp, *t;
243 int found = 0; 243 int found = 0;
244 244
245 if (card->options.sniffer)
246 return 0;
245 list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) { 247 list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) {
246 if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && 248 if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
247 (tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) 249 (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
@@ -457,6 +459,8 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
457 QETH_DBF_TEXT(TRACE, 2, "sdiplist"); 459 QETH_DBF_TEXT(TRACE, 2, "sdiplist");
458 QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *)); 460 QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *));
459 461
462 if (card->options.sniffer)
463 return;
460 spin_lock_irqsave(&card->ip_lock, flags); 464 spin_lock_irqsave(&card->ip_lock, flags);
461 tbd_list = card->ip_tbd_list; 465 tbd_list = card->ip_tbd_list;
462 card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC); 466 card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
@@ -495,7 +499,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
495 spin_unlock_irqrestore(&card->ip_lock, flags); 499 spin_unlock_irqrestore(&card->ip_lock, flags);
496 rc = qeth_l3_deregister_addr_entry(card, addr); 500 rc = qeth_l3_deregister_addr_entry(card, addr);
497 spin_lock_irqsave(&card->ip_lock, flags); 501 spin_lock_irqsave(&card->ip_lock, flags);
498 if (!rc || (rc == IPA_RC_PRIMARY_ALREADY_DEFINED)) 502 if (!rc || (rc == IPA_RC_IP_ADDRESS_NOT_DEFINED))
499 kfree(addr); 503 kfree(addr);
500 else 504 else
501 list_add_tail(&addr->entry, &card->ip_list); 505 list_add_tail(&addr->entry, &card->ip_list);
@@ -513,6 +517,8 @@ static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean,
513 unsigned long flags; 517 unsigned long flags;
514 518
515 QETH_DBF_TEXT(TRACE, 4, "clearip"); 519 QETH_DBF_TEXT(TRACE, 4, "clearip");
520 if (recover && card->options.sniffer)
521 return;
516 spin_lock_irqsave(&card->ip_lock, flags); 522 spin_lock_irqsave(&card->ip_lock, flags);
517 /* clear todo list */ 523 /* clear todo list */
518 list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry) { 524 list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry) {
@@ -1674,6 +1680,76 @@ static int qeth_l3_get_unique_id(struct qeth_card *card)
1674 return rc; 1680 return rc;
1675} 1681}
1676 1682
1683static int
1684qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply,
1685 unsigned long data)
1686{
1687 struct qeth_ipa_cmd *cmd;
1688 __u16 rc;
1689
1690 QETH_DBF_TEXT(SETUP, 2, "diastrcb");
1691
1692 cmd = (struct qeth_ipa_cmd *)data;
1693 rc = cmd->hdr.return_code;
1694 if (rc) {
1695 QETH_DBF_TEXT_(TRACE, 2, "dxter%x", rc);
1696 if (cmd->data.diagass.action == QETH_DIAGS_CMD_TRACE_ENABLE) {
1697 switch (rc) {
1698 case IPA_RC_HARDWARE_AUTH_ERROR:
1699 dev_warn(&card->gdev->dev, "The device is not "
1700 "authorized to run as a HiperSockets "
1701 "network traffic analyzer\n");
1702 break;
1703 case IPA_RC_TRACE_ALREADY_ACTIVE:
1704 dev_warn(&card->gdev->dev, "A HiperSockets "
1705 "network traffic analyzer is already "
1706 "active in the HiperSockets LAN\n");
1707 break;
1708 default:
1709 break;
1710 }
1711 }
1712 return 0;
1713 }
1714
1715 switch (cmd->data.diagass.action) {
1716 case QETH_DIAGS_CMD_TRACE_QUERY:
1717 break;
1718 case QETH_DIAGS_CMD_TRACE_DISABLE:
1719 card->info.promisc_mode = SET_PROMISC_MODE_OFF;
1720 dev_info(&card->gdev->dev, "The HiperSockets network traffic "
1721 "analyzer is deactivated\n");
1722 break;
1723 case QETH_DIAGS_CMD_TRACE_ENABLE:
1724 card->info.promisc_mode = SET_PROMISC_MODE_ON;
1725 dev_info(&card->gdev->dev, "The HiperSockets network traffic "
1726 "analyzer is activated\n");
1727 break;
1728 default:
1729 QETH_DBF_MESSAGE(2, "Unknown sniffer action (0x%04x) on %s\n",
1730 cmd->data.diagass.action, QETH_CARD_IFNAME(card));
1731 }
1732
1733 return 0;
1734}
1735
1736static int
1737qeth_diags_trace(struct qeth_card *card, enum qeth_diags_trace_cmds diags_cmd)
1738{
1739 struct qeth_cmd_buffer *iob;
1740 struct qeth_ipa_cmd *cmd;
1741
1742 QETH_DBF_TEXT(SETUP, 2, "diagtrac");
1743
1744 iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
1745 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
1746 cmd->data.diagass.subcmd_len = 16;
1747 cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRACE;
1748 cmd->data.diagass.type = QETH_DIAGS_TYPE_HIPERSOCKET;
1749 cmd->data.diagass.action = diags_cmd;
1750 return qeth_send_ipa_cmd(card, iob, qeth_diags_trace_cb, NULL);
1751}
1752
1677static void qeth_l3_get_mac_for_ipm(__u32 ipm, char *mac, 1753static void qeth_l3_get_mac_for_ipm(__u32 ipm, char *mac,
1678 struct net_device *dev) 1754 struct net_device *dev)
1679{ 1755{
@@ -1951,7 +2027,10 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
1951 case QETH_CAST_ANYCAST: 2027 case QETH_CAST_ANYCAST:
1952 case QETH_CAST_NOCAST: 2028 case QETH_CAST_NOCAST:
1953 default: 2029 default:
1954 skb->pkt_type = PACKET_HOST; 2030 if (card->options.sniffer)
2031 skb->pkt_type = PACKET_OTHERHOST;
2032 else
2033 skb->pkt_type = PACKET_HOST;
1955 memcpy(tg_addr, card->dev->dev_addr, 2034 memcpy(tg_addr, card->dev->dev_addr,
1956 card->dev->addr_len); 2035 card->dev->addr_len);
1957 } 2036 }
@@ -2007,7 +2086,6 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
2007 int offset; 2086 int offset;
2008 __u16 vlan_tag = 0; 2087 __u16 vlan_tag = 0;
2009 unsigned int len; 2088 unsigned int len;
2010
2011 /* get first element of current buffer */ 2089 /* get first element of current buffer */
2012 element = (struct qdio_buffer_element *)&buf->buffer->element[0]; 2090 element = (struct qdio_buffer_element *)&buf->buffer->element[0];
2013 offset = 0; 2091 offset = 0;
@@ -2026,7 +2104,7 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
2026 case QETH_HEADER_TYPE_LAYER3: 2104 case QETH_HEADER_TYPE_LAYER3:
2027 vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr); 2105 vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr);
2028 len = skb->len; 2106 len = skb->len;
2029 if (vlan_tag) 2107 if (vlan_tag && !card->options.sniffer)
2030 if (card->vlangrp) 2108 if (card->vlangrp)
2031 vlan_hwaccel_rx(skb, card->vlangrp, 2109 vlan_hwaccel_rx(skb, card->vlangrp,
2032 vlan_tag); 2110 vlan_tag);
@@ -2037,6 +2115,16 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
2037 else 2115 else
2038 netif_rx(skb); 2116 netif_rx(skb);
2039 break; 2117 break;
2118 case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
2119 skb->pkt_type = PACKET_HOST;
2120 skb->protocol = eth_type_trans(skb, skb->dev);
2121 if (card->options.checksum_type == NO_CHECKSUMMING)
2122 skb->ip_summed = CHECKSUM_UNNECESSARY;
2123 else
2124 skb->ip_summed = CHECKSUM_NONE;
2125 len = skb->len;
2126 netif_receive_skb(skb);
2127 break;
2040 default: 2128 default:
2041 dev_kfree_skb_any(skb); 2129 dev_kfree_skb_any(skb);
2042 QETH_DBF_TEXT(TRACE, 3, "inbunkno"); 2130 QETH_DBF_TEXT(TRACE, 3, "inbunkno");
@@ -2118,6 +2206,9 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
2118 QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); 2206 QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
2119 2207
2120 qeth_set_allowed_threads(card, 0, 1); 2208 qeth_set_allowed_threads(card, 0, 1);
2209 if (card->options.sniffer &&
2210 (card->info.promisc_mode == SET_PROMISC_MODE_ON))
2211 qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
2121 if (card->read.state == CH_STATE_UP && 2212 if (card->read.state == CH_STATE_UP &&
2122 card->write.state == CH_STATE_UP && 2213 card->write.state == CH_STATE_UP &&
2123 (card->state == CARD_STATE_UP)) { 2214 (card->state == CARD_STATE_UP)) {
@@ -2162,6 +2253,36 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
2162 return rc; 2253 return rc;
2163} 2254}
2164 2255
2256/*
2257 * test for and Switch promiscuous mode (on or off)
2258 * either for guestlan or HiperSocket Sniffer
2259 */
2260static void
2261qeth_l3_handle_promisc_mode(struct qeth_card *card)
2262{
2263 struct net_device *dev = card->dev;
2264
2265 if (((dev->flags & IFF_PROMISC) &&
2266 (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
2267 (!(dev->flags & IFF_PROMISC) &&
2268 (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
2269 return;
2270
2271 if (card->info.guestlan) { /* Guestlan trace */
2272 if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
2273 qeth_setadp_promisc_mode(card);
2274 } else if (card->options.sniffer && /* HiperSockets trace */
2275 qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) {
2276 if (dev->flags & IFF_PROMISC) {
2277 QETH_DBF_TEXT(TRACE, 3, "+promisc");
2278 qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_ENABLE);
2279 } else {
2280 QETH_DBF_TEXT(TRACE, 3, "-promisc");
2281 qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
2282 }
2283 }
2284}
2285
2165static void qeth_l3_set_multicast_list(struct net_device *dev) 2286static void qeth_l3_set_multicast_list(struct net_device *dev)
2166{ 2287{
2167 struct qeth_card *card = dev->ml_priv; 2288 struct qeth_card *card = dev->ml_priv;
@@ -2170,15 +2291,17 @@ static void qeth_l3_set_multicast_list(struct net_device *dev)
2170 if (qeth_threads_running(card, QETH_RECOVER_THREAD) && 2291 if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
2171 (card->state != CARD_STATE_UP)) 2292 (card->state != CARD_STATE_UP))
2172 return; 2293 return;
2173 qeth_l3_delete_mc_addresses(card); 2294 if (!card->options.sniffer) {
2174 qeth_l3_add_multicast_ipv4(card); 2295 qeth_l3_delete_mc_addresses(card);
2296 qeth_l3_add_multicast_ipv4(card);
2175#ifdef CONFIG_QETH_IPV6 2297#ifdef CONFIG_QETH_IPV6
2176 qeth_l3_add_multicast_ipv6(card); 2298 qeth_l3_add_multicast_ipv6(card);
2177#endif 2299#endif
2178 qeth_l3_set_ip_addr_list(card); 2300 qeth_l3_set_ip_addr_list(card);
2179 if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) 2301 if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
2180 return; 2302 return;
2181 qeth_setadp_promisc_mode(card); 2303 }
2304 qeth_l3_handle_promisc_mode(card);
2182} 2305}
2183 2306
2184static const char *qeth_l3_arp_get_error_cause(int *rc) 2307static const char *qeth_l3_arp_get_error_cause(int *rc)
@@ -2778,8 +2901,9 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2778 int nr_frags; 2901 int nr_frags;
2779 2902
2780 if ((card->info.type == QETH_CARD_TYPE_IQD) && 2903 if ((card->info.type == QETH_CARD_TYPE_IQD) &&
2781 (skb->protocol != htons(ETH_P_IPV6)) && 2904 (((skb->protocol != htons(ETH_P_IPV6)) &&
2782 (skb->protocol != htons(ETH_P_IP))) 2905 (skb->protocol != htons(ETH_P_IP))) ||
2906 card->options.sniffer))
2783 goto tx_drop; 2907 goto tx_drop;
2784 2908
2785 if ((card->state != CARD_STATE_UP) || !card->lan_online) { 2909 if ((card->state != CARD_STATE_UP) || !card->lan_online) {
@@ -3155,7 +3279,7 @@ static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
3155 index = i % QDIO_MAX_BUFFERS_PER_Q; 3279 index = i % QDIO_MAX_BUFFERS_PER_Q;
3156 buffer = &card->qdio.in_q->bufs[index]; 3280 buffer = &card->qdio.in_q->bufs[index];
3157 if (!(qdio_err && 3281 if (!(qdio_err &&
3158 qeth_check_qdio_errors(buffer->buffer, 3282 qeth_check_qdio_errors(card, buffer->buffer,
3159 qdio_err, "qinerr"))) 3283 qdio_err, "qinerr")))
3160 qeth_l3_process_inbound_buffer(card, buffer, index); 3284 qeth_l3_process_inbound_buffer(card, buffer, index);
3161 /* clear buffer and give back to hardware */ 3285 /* clear buffer and give back to hardware */
@@ -3250,20 +3374,22 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
3250 goto out_remove; 3374 goto out_remove;
3251 } else 3375 } else
3252 card->lan_online = 1; 3376 card->lan_online = 1;
3253 qeth_l3_set_large_send(card, card->options.large_send);
3254 3377
3255 rc = qeth_l3_setadapter_parms(card); 3378 rc = qeth_l3_setadapter_parms(card);
3256 if (rc) 3379 if (rc)
3257 QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); 3380 QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
3258 rc = qeth_l3_start_ipassists(card); 3381 if (!card->options.sniffer) {
3259 if (rc) 3382 rc = qeth_l3_start_ipassists(card);
3260 QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); 3383 if (rc)
3261 rc = qeth_l3_setrouting_v4(card); 3384 QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
3262 if (rc) 3385 qeth_l3_set_large_send(card, card->options.large_send);
3263 QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc); 3386 rc = qeth_l3_setrouting_v4(card);
3264 rc = qeth_l3_setrouting_v6(card); 3387 if (rc)
3265 if (rc) 3388 QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc);
3266 QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); 3389 rc = qeth_l3_setrouting_v6(card);
3390 if (rc)
3391 QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
3392 }
3267 netif_tx_disable(card->dev); 3393 netif_tx_disable(card->dev);
3268 3394
3269 rc = qeth_init_qdio_queues(card); 3395 rc = qeth_init_qdio_queues(card);