cxgb3: manage private iSCSI IP address
The accelerated iSCSI traffic could use a private IP address unknown to the OS: - The IP address is required in both drivers to manage ARP requests and connection set up. - Added an control call to retrieve the ip address. - Reply to ARP requests dedicated to the private IP address. Signed-off-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: Karen Xie <kxie@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
221b3d60cb
commit
a109a5b916
@ -36,6 +36,7 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <net/arp.h>
|
||||
#include "common.h"
|
||||
#include "regs.h"
|
||||
#include "sge_defs.h"
|
||||
@ -1862,6 +1863,54 @@ static void restart_tx(struct sge_qset *qs)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cxgb3_arp_process - process an ARP request probing a private IP address
|
||||
* @adapter: the adapter
|
||||
* @skb: the skbuff containing the ARP request
|
||||
*
|
||||
* Check if the ARP request is probing the private IP address
|
||||
* dedicated to iSCSI, generate an ARP reply if so.
|
||||
*/
|
||||
static void cxgb3_arp_process(struct adapter *adapter, struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
struct port_info *pi;
|
||||
struct arphdr *arp;
|
||||
unsigned char *arp_ptr;
|
||||
unsigned char *sha;
|
||||
__be32 sip, tip;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
arp = arp_hdr(skb);
|
||||
|
||||
if (arp->ar_op != htons(ARPOP_REQUEST))
|
||||
return;
|
||||
|
||||
arp_ptr = (unsigned char *)(arp + 1);
|
||||
sha = arp_ptr;
|
||||
arp_ptr += dev->addr_len;
|
||||
memcpy(&sip, arp_ptr, sizeof(sip));
|
||||
arp_ptr += sizeof(sip);
|
||||
arp_ptr += dev->addr_len;
|
||||
memcpy(&tip, arp_ptr, sizeof(tip));
|
||||
|
||||
pi = netdev_priv(dev);
|
||||
if (tip != pi->iscsi_ipv4addr)
|
||||
return;
|
||||
|
||||
arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
|
||||
dev->dev_addr, sha);
|
||||
|
||||
}
|
||||
|
||||
static inline int is_arp(struct sk_buff *skb)
|
||||
{
|
||||
return skb->protocol == htons(ETH_P_ARP);
|
||||
}
|
||||
|
||||
/**
|
||||
* rx_eth - process an ingress ethernet packet
|
||||
* @adap: the adapter
|
||||
@ -1885,7 +1934,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
|
||||
pi = netdev_priv(skb->dev);
|
||||
if (pi->rx_csum_offload && p->csum_valid && p->csum == htons(0xffff) &&
|
||||
!p->fragment) {
|
||||
rspq_to_qset(rq)->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
|
||||
qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
} else
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
@ -1900,16 +1949,28 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
|
||||
grp,
|
||||
ntohs(p->vlan),
|
||||
p);
|
||||
else
|
||||
else {
|
||||
if (unlikely(pi->iscsi_ipv4addr &&
|
||||
is_arp(skb))) {
|
||||
unsigned short vtag = ntohs(p->vlan) &
|
||||
VLAN_VID_MASK;
|
||||
skb->dev = vlan_group_get_device(grp,
|
||||
vtag);
|
||||
cxgb3_arp_process(adap, skb);
|
||||
}
|
||||
__vlan_hwaccel_rx(skb, grp, ntohs(p->vlan),
|
||||
rq->polling);
|
||||
}
|
||||
else
|
||||
dev_kfree_skb_any(skb);
|
||||
} else if (rq->polling) {
|
||||
if (lro)
|
||||
lro_receive_skb(&qs->lro_mgr, skb, p);
|
||||
else
|
||||
else {
|
||||
if (unlikely(pi->iscsi_ipv4addr && is_arp(skb)))
|
||||
cxgb3_arp_process(adap, skb);
|
||||
netif_receive_skb(skb);
|
||||
}
|
||||
} else
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
Reference in New Issue
Block a user