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

net/af_iucv: locate IUCV header via skb_network_header()

This patch attempts to untangle the TX and RX code in qeth from
af_iucv's respective HiperTransport path:
On the TX side, pointing skb_network_header() at the IUCV header
means that qeth_l3_fill_af_iucv_hdr() no longer needs a magical offset
to access the header.
On the RX side, qeth pulls the (fake) L2 header off the skb like any
normal ethernet driver would. This makes working with the IUCV header
in af_iucv easier, since we no longer have to assume a fixed skb layout.

While at it, replace the open-coded length checks in af_iucv's RX path
with pskb_may_pull().

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Julian Wiedmann and committed by
David S. Miller
cd11d112 a2eb0ad5

+23 -36
+5 -7
drivers/s390/net/qeth_l3_main.c
··· 1348 1348 static int qeth_l3_process_inbound_buffer(struct qeth_card *card, 1349 1349 int budget, int *done) 1350 1350 { 1351 + struct net_device *dev = card->dev; 1351 1352 int work_done = 0; 1352 1353 struct sk_buff *skb; 1353 1354 struct qeth_hdr *hdr; ··· 1370 1369 magic = *(__u16 *)skb->data; 1371 1370 if ((card->info.type == QETH_CARD_TYPE_IQD) && 1372 1371 (magic == ETH_P_AF_IUCV)) { 1373 - skb->protocol = cpu_to_be16(ETH_P_AF_IUCV); 1374 1372 len = skb->len; 1375 - card->dev->header_ops->create(skb, card->dev, 0, 1376 - card->dev->dev_addr, "FAKELL", len); 1377 - skb_reset_mac_header(skb); 1373 + dev_hard_header(skb, dev, ETH_P_AF_IUCV, 1374 + dev->dev_addr, "FAKELL", len); 1375 + skb->protocol = eth_type_trans(skb, dev); 1378 1376 netif_receive_skb(skb); 1379 1377 } else { 1380 1378 qeth_l3_rebuild_skb(card, skb, hdr); ··· 2005 2005 unsigned int data_len) 2006 2006 { 2007 2007 char daddr[16]; 2008 - struct af_iucv_trans_hdr *iucv_hdr; 2009 2008 2010 2009 hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3; 2011 2010 hdr->hdr.l3.length = data_len; 2012 2011 hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST; 2013 2012 2014 - iucv_hdr = (struct af_iucv_trans_hdr *)(skb_mac_header(skb) + ETH_HLEN); 2015 2013 memset(daddr, 0, sizeof(daddr)); 2016 2014 daddr[0] = 0xfe; 2017 2015 daddr[1] = 0x80; 2018 - memcpy(&daddr[8], iucv_hdr->destUserID, 8); 2016 + memcpy(&daddr[8], iucv_trans_hdr(skb)->destUserID, 8); 2019 2017 memcpy(hdr->hdr.l3.next_hop.ipv6_addr, daddr, 16); 2020 2018 } 2021 2019
+5
include/net/iucv/af_iucv.h
··· 80 80 u8 pad; /* total 104 bytes */ 81 81 } __packed; 82 82 83 + static inline struct af_iucv_trans_hdr *iucv_trans_hdr(struct sk_buff *skb) 84 + { 85 + return (struct af_iucv_trans_hdr *)skb_network_header(skb); 86 + } 87 + 83 88 enum iucv_tx_notify { 84 89 /* transmission of skb is completed and was successful */ 85 90 TX_NOTIFY_OK = 0,
+13 -29
net/iucv/af_iucv.c
··· 320 320 struct sk_buff *nskb; 321 321 int err, confirm_recv = 0; 322 322 323 - memset(skb->head, 0, ETH_HLEN); 324 - phs_hdr = skb_push(skb, sizeof(struct af_iucv_trans_hdr)); 325 - skb_reset_mac_header(skb); 323 + phs_hdr = skb_push(skb, sizeof(*phs_hdr)); 324 + memset(phs_hdr, 0, sizeof(*phs_hdr)); 326 325 skb_reset_network_header(skb); 327 - skb_push(skb, ETH_HLEN); 328 - skb_reset_mac_header(skb); 329 - memset(phs_hdr, 0, sizeof(struct af_iucv_trans_hdr)); 330 326 331 327 phs_hdr->magic = ETH_P_AF_IUCV; 332 328 phs_hdr->version = 1; ··· 345 349 ASCEBC(phs_hdr->srcAppName, sizeof(phs_hdr->srcAppName)); 346 350 if (imsg) 347 351 memcpy(&phs_hdr->iucv_hdr, imsg, sizeof(struct iucv_message)); 352 + 353 + skb_push(skb, ETH_HLEN); 354 + memset(skb->data, 0, ETH_HLEN); 348 355 349 356 skb->dev = iucv->hs_dev; 350 357 if (!skb->dev) { ··· 1942 1943 /***************** HiperSockets transport callbacks ********************/ 1943 1944 static void afiucv_swap_src_dest(struct sk_buff *skb) 1944 1945 { 1945 - struct af_iucv_trans_hdr *trans_hdr = 1946 - (struct af_iucv_trans_hdr *)skb->data; 1946 + struct af_iucv_trans_hdr *trans_hdr = iucv_trans_hdr(skb); 1947 1947 char tmpID[8]; 1948 1948 char tmpName[8]; 1949 1949 ··· 1965 1967 **/ 1966 1968 static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb) 1967 1969 { 1970 + struct af_iucv_trans_hdr *trans_hdr = iucv_trans_hdr(skb); 1968 1971 struct sock *nsk; 1969 1972 struct iucv_sock *iucv, *niucv; 1970 - struct af_iucv_trans_hdr *trans_hdr; 1971 1973 int err; 1972 1974 1973 1975 iucv = iucv_sk(sk); 1974 - trans_hdr = (struct af_iucv_trans_hdr *)skb->data; 1975 1976 if (!iucv) { 1976 1977 /* no sock - connection refused */ 1977 1978 afiucv_swap_src_dest(skb); ··· 2031 2034 static int afiucv_hs_callback_synack(struct sock *sk, struct sk_buff *skb) 2032 2035 { 2033 2036 struct iucv_sock *iucv = iucv_sk(sk); 2034 - struct af_iucv_trans_hdr *trans_hdr = 2035 - (struct af_iucv_trans_hdr *)skb->data; 2036 2037 2037 2038 if (!iucv) 2038 2039 goto out; 2039 2040 if (sk->sk_state != IUCV_BOUND) 2040 2041 goto out; 2041 2042 bh_lock_sock(sk); 2042 - iucv->msglimit_peer = trans_hdr->window; 2043 + iucv->msglimit_peer = iucv_trans_hdr(skb)->window; 2043 2044 sk->sk_state = IUCV_CONNECTED; 2044 2045 sk->sk_state_change(sk); 2045 2046 bh_unlock_sock(sk); ··· 2093 2098 static int afiucv_hs_callback_win(struct sock *sk, struct sk_buff *skb) 2094 2099 { 2095 2100 struct iucv_sock *iucv = iucv_sk(sk); 2096 - struct af_iucv_trans_hdr *trans_hdr = 2097 - (struct af_iucv_trans_hdr *)skb->data; 2098 2101 2099 2102 if (!iucv) 2100 2103 return NET_RX_SUCCESS; ··· 2100 2107 if (sk->sk_state != IUCV_CONNECTED) 2101 2108 return NET_RX_SUCCESS; 2102 2109 2103 - atomic_sub(trans_hdr->window, &iucv->msg_sent); 2110 + atomic_sub(iucv_trans_hdr(skb)->window, &iucv->msg_sent); 2104 2111 iucv_sock_wake_msglim(sk); 2105 2112 return NET_RX_SUCCESS; 2106 2113 } ··· 2163 2170 int err = NET_RX_SUCCESS; 2164 2171 char nullstring[8]; 2165 2172 2166 - if (skb->len < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) { 2167 - WARN_ONCE(1, "AF_IUCV too short skb, len=%d, min=%d", 2168 - (int)skb->len, 2169 - (int)(ETH_HLEN + sizeof(struct af_iucv_trans_hdr))); 2173 + if (!pskb_may_pull(skb, sizeof(*trans_hdr))) { 2174 + WARN_ONCE(1, "AF_IUCV failed to receive skb, len=%u", skb->len); 2170 2175 kfree_skb(skb); 2171 2176 return NET_RX_SUCCESS; 2172 2177 } 2173 - if (skb_headlen(skb) < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) 2174 - if (skb_linearize(skb)) { 2175 - WARN_ONCE(1, "AF_IUCV skb_linearize failed, len=%d", 2176 - (int)skb->len); 2177 - kfree_skb(skb); 2178 - return NET_RX_SUCCESS; 2179 - } 2180 - skb_pull(skb, ETH_HLEN); 2181 - trans_hdr = (struct af_iucv_trans_hdr *)skb->data; 2178 + 2179 + trans_hdr = iucv_trans_hdr(skb); 2182 2180 EBCASC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName)); 2183 2181 EBCASC(trans_hdr->destUserID, sizeof(trans_hdr->destUserID)); 2184 2182 EBCASC(trans_hdr->srcAppName, sizeof(trans_hdr->srcAppName));