struct nes_cm_node *);
static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
struct nes_cm_node *);
-static void mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
+static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
struct sk_buff *);
static int mini_cm_dealloc_core(struct nes_cm_core *);
static int mini_cm_get(struct nes_cm_core *);
static int mini_cm_set(struct nes_cm_core *, u32, u32);
-static struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *,
+static void form_cm_frame(struct sk_buff *, struct nes_cm_node *,
void *, u32, void *, u32, u8);
-static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node);
static int add_ref_cm_node(struct nes_cm_node *);
static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
* form_cm_frame - get a free packet and build empty frame Use
* node info to build.
*/
-static struct sk_buff *form_cm_frame(struct sk_buff *skb,
+static void form_cm_frame(struct sk_buff *skb,
struct nes_cm_node *cm_node, void *options, u32 optionsize,
void *data, u32 datasize, u8 flags)
{
skb_shinfo(skb)->nr_frags = 0;
cm_packets_created++;
- return skb;
}
nes_debug(NES_DBG_CM, "State : %u \n", core->state);
- nes_debug(NES_DBG_CM, "Tx Free cnt : %u \n", skb_queue_len(&core->tx_free_list));
nes_debug(NES_DBG_CM, "Listen Nodes : %u \n", atomic_read(&core->listen_node_cnt));
nes_debug(NES_DBG_CM, "Active Nodes : %u \n", atomic_read(&core->node_cnt));
int ret = 0;
u32 was_timer_set;
- if (!cm_node)
- return -EINVAL;
new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC);
if (!new_send)
return -1;
optionssize += 1;
if (!skb)
- skb = get_free_pkt(cm_node);
+ skb = dev_alloc_skb(MAX_CM_BUFFER);
if (!skb) {
nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
return -1;
int flags = SET_RST | SET_ACK;
if (!skb)
- skb = get_free_pkt(cm_node);
+ skb = dev_alloc_skb(MAX_CM_BUFFER);
if (!skb) {
nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
return -1;
int ret;
if (!skb)
- skb = get_free_pkt(cm_node);
+ skb = dev_alloc_skb(MAX_CM_BUFFER);
if (!skb) {
nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
/* if we didn't get a frame get one */
if (!skb)
- skb = get_free_pkt(cm_node);
+ skb = dev_alloc_skb(MAX_CM_BUFFER);
if (!skb) {
nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
}
-/**
- * get_free_pkt
- */
-static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node)
-{
- struct sk_buff *skb, *new_skb;
-
- /* check to see if we need to repopulate the free tx pkt queue */
- if (skb_queue_len(&cm_node->cm_core->tx_free_list) < NES_CM_FREE_PKT_LO_WATERMARK) {
- while (skb_queue_len(&cm_node->cm_core->tx_free_list) <
- cm_node->cm_core->free_tx_pkt_max) {
- /* replace the frame we took, we won't get it back */
- new_skb = dev_alloc_skb(cm_node->cm_core->mtu);
- BUG_ON(!new_skb);
- /* add a replacement frame to the free tx list head */
- skb_queue_head(&cm_node->cm_core->tx_free_list, new_skb);
- }
- }
-
- skb = skb_dequeue(&cm_node->cm_core->tx_free_list);
-
- return skb;
-}
-
-
-/**
- * make_hashkey - generate hash key from node tuple
- */
-static inline int make_hashkey(u16 loc_port, nes_addr_t loc_addr, u16 rem_port,
- nes_addr_t rem_addr)
-{
- u32 hashkey = 0;
-
- hashkey = loc_addr + rem_addr + loc_port + rem_port;
- hashkey = (hashkey % NES_CM_HASHTABLE_SIZE);
-
- return hashkey;
-}
-
-
/**
* find_node - find a cm node that matches the reference cm node
*/
u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
{
unsigned long flags;
- u32 hashkey;
struct list_head *hte;
struct nes_cm_node *cm_node;
-
- /* make a hash index key for this packet */
- hashkey = make_hashkey(loc_port, loc_addr, rem_port, rem_addr);
+ __be32 tmp_addr = cpu_to_be32(loc_addr);
/* get a handle on the hte */
hte = &cm_core->connected_nodes;
- nes_debug(NES_DBG_CM, "Searching for an owner node: " NIPQUAD_FMT ":%x from core %p->%p\n",
- HIPQUAD(loc_addr), loc_port, cm_core, hte);
+ nes_debug(NES_DBG_CM, "Searching for an owner node: %pI4:%x from core %p->%p\n",
+ &tmp_addr, loc_port, cm_core, hte);
/* walk list and find cm_node associated with this session ID */
spin_lock_irqsave(&cm_core->ht_lock, flags);
{
unsigned long flags;
struct nes_cm_listener *listen_node;
+ __be32 tmp_addr = cpu_to_be32(dst_addr);
/* walk list and find cm_node associated with this session ID */
spin_lock_irqsave(&cm_core->listen_list_lock, flags);
}
spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
- nes_debug(NES_DBG_CM, "Unable to find listener for " NIPQUAD_FMT ":%x\n",
- HIPQUAD(dst_addr), dst_port);
+ nes_debug(NES_DBG_CM, "Unable to find listener for %pI4:%x\n",
+ &tmp_addr, dst_port);
/* no listener */
return NULL;
static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
{
unsigned long flags;
- u32 hashkey;
struct list_head *hte;
if (!cm_node || !cm_core)
nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n",
cm_node);
- /* first, make an index into our hash table */
- hashkey = make_hashkey(cm_node->loc_port, cm_node->loc_addr,
- cm_node->rem_port, cm_node->rem_addr);
- cm_node->hashkey = hashkey;
-
spin_lock_irqsave(&cm_core->ht_lock, flags);
/* get a handle on the hash table element (list head for this slot) */
struct flowi fl;
struct neighbour *neigh;
int rc = -1;
- DECLARE_MAC_BUF(mac);
memset(&fl, 0, sizeof fl);
fl.nl_u.ip4_u.daddr = htonl(dst_ip);
if (neigh) {
if (neigh->nud_state & NUD_VALID) {
nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X"
- " is %s, Gateway is 0x%08X \n", dst_ip,
- print_mac(mac, neigh->ha), ntohl(rt->rt_gateway));
+ " is %pM, Gateway is 0x%08X \n", dst_ip,
+ neigh->ha, ntohl(rt->rt_gateway));
nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
dst_ip, NES_ARP_ADD);
rc = nes_arp_table(nesvnic->nesdev, dst_ip, NULL,
int arpindex = 0;
struct nes_device *nesdev;
struct nes_adapter *nesadapter;
- DECLARE_MAC_BUF(mac);
/* create an hte and cm_node for this instance */
cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
cm_node->loc_port = cm_info->loc_port;
cm_node->rem_port = cm_info->rem_port;
cm_node->send_write0 = send_first;
- nes_debug(NES_DBG_CM, "Make node addresses : loc = " NIPQUAD_FMT
- ":%x, rem = " NIPQUAD_FMT ":%x\n",
- HIPQUAD(cm_node->loc_addr), cm_node->loc_port,
- HIPQUAD(cm_node->rem_addr), cm_node->rem_port);
+ nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n",
+ &cm_node->loc_addr, cm_node->loc_port,
+ &cm_node->rem_addr, cm_node->rem_port);
cm_node->listener = listener;
cm_node->netdev = nesvnic->netdev;
cm_node->cm_id = cm_info->cm_id;
cm_node->loopbackpartner = NULL;
/* get the mac addr for the remote node */
- arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
+ if (ipv4_is_loopback(htonl(cm_node->rem_addr)))
+ arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
+ else
+ arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
if (arpindex < 0) {
arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr);
if (arpindex < 0) {
/* copy the mac addr to node context */
memcpy(cm_node->rem_mac, nesadapter->arp_table[arpindex].mac_addr, ETH_ALEN);
- nes_debug(NES_DBG_CM, "Remote mac addr from arp table: %s\n",
- print_mac(mac, cm_node->rem_mac));
+ nes_debug(NES_DBG_CM, "Remote mac addr from arp table: %pM\n",
+ cm_node->rem_mac);
add_hte_node(cm_core, cm_node);
atomic_inc(&cm_nodes_created);
static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
struct tcphdr *tcph)
{
- atomic_inc(&cm_resets_recvd);
nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
"refcnt=%d\n", cm_node, cm_node->state,
atomic_read(&cm_node->ref_count));
int optionsize;
optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
- skb_pull(skb, tcph->doff << 2);
+ skb_trim(skb, 0);
inc_sequence = ntohl(tcph->seq);
switch (cm_node->state) {
cm_node->state = NES_CM_STATE_SYN_RCVD;
send_syn(cm_node, 1, skb);
break;
+ case NES_CM_STATE_CLOSED:
+ cleanup_retrans_entry(cm_node);
+ send_reset(cm_node, skb);
+ break;
case NES_CM_STATE_TSA:
case NES_CM_STATE_ESTABLISHED:
case NES_CM_STATE_FIN_WAIT1:
case NES_CM_STATE_LAST_ACK:
case NES_CM_STATE_CLOSING:
case NES_CM_STATE_UNKNOWN:
- case NES_CM_STATE_CLOSED:
default:
drop_packet(skb);
break;
int optionsize;
optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
- skb_pull(skb, tcph->doff << 2);
+ skb_trim(skb, 0);
inc_sequence = ntohl(tcph->seq);
switch (cm_node->state) {
case NES_CM_STATE_SYN_SENT:
/* passive open, so should not be here */
passive_open_err(cm_node, skb, 1);
break;
+ case NES_CM_STATE_LISTENING:
+ case NES_CM_STATE_CLOSED:
+ cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
+ cleanup_retrans_entry(cm_node);
+ send_reset(cm_node, skb);
+ break;
case NES_CM_STATE_ESTABLISHED:
case NES_CM_STATE_FIN_WAIT1:
case NES_CM_STATE_FIN_WAIT2:
case NES_CM_STATE_TSA:
case NES_CM_STATE_CLOSING:
case NES_CM_STATE_UNKNOWN:
- case NES_CM_STATE_CLOSED:
case NES_CM_STATE_MPAREQ_SENT:
default:
drop_packet(skb);
u32 inc_sequence;
u32 rem_seq_ack;
u32 rem_seq;
+ int ret;
+ int optionsize;
+ u32 temp_seq = cm_node->tcp_cntxt.loc_seq_num;
+
+ optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
+ cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
+
if (check_seq(cm_node, tcph, skb))
return;
switch (cm_node->state) {
case NES_CM_STATE_SYN_RCVD:
/* Passive OPEN */
+ ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 1);
+ if (ret)
+ break;
cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
+ cm_node->tcp_cntxt.loc_seq_num = temp_seq;
+ if (cm_node->tcp_cntxt.rem_ack_num !=
+ cm_node->tcp_cntxt.loc_seq_num) {
+ nes_debug(NES_DBG_CM, "rem_ack_num != loc_seq_num\n");
+ cleanup_retrans_entry(cm_node);
+ send_reset(cm_node, skb);
+ return;
+ }
cm_node->state = NES_CM_STATE_ESTABLISHED;
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
dev_kfree_skb_any(skb);
}
break;
+ case NES_CM_STATE_LISTENING:
+ case NES_CM_STATE_CLOSED:
+ cleanup_retrans_entry(cm_node);
+ send_reset(cm_node, skb);
+ break;
case NES_CM_STATE_FIN_WAIT1:
case NES_CM_STATE_SYN_SENT:
case NES_CM_STATE_FIN_WAIT2:
case NES_CM_STATE_TSA:
- case NES_CM_STATE_CLOSED:
case NES_CM_STATE_MPAREQ_RCVD:
case NES_CM_STATE_LAST_ACK:
case NES_CM_STATE_CLOSING:
nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n",
__func__, cm_node);
if (passive)
- passive_open_err(cm_node, skb, 0);
+ passive_open_err(cm_node, skb, 1);
else
- active_open_err(cm_node, skb, 0);
+ active_open_err(cm_node, skb, 1);
return 1;
}
}
* recv_pkt - recv an ETHERNET packet, and process it through CM
* node state machine
*/
-static void mini_cm_recv_pkt(struct nes_cm_core *cm_core,
+static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
struct nes_vnic *nesvnic, struct sk_buff *skb)
{
struct nes_cm_node *cm_node = NULL;
struct iphdr *iph;
struct tcphdr *tcph;
struct nes_cm_info nfo;
+ int skb_handled = 1;
+ __be32 tmp_daddr, tmp_saddr;
if (!skb)
- return;
+ return 0;
if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
- dev_kfree_skb_any(skb);
- return;
+ return 0;
}
iph = (struct iphdr *)skb->data;
tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
- skb_reset_network_header(skb);
- skb_set_transport_header(skb, sizeof(*tcph));
- if (!tcph) {
- dev_kfree_skb_any(skb);
- return;
- }
- skb->len = ntohs(iph->tot_len);
nfo.loc_addr = ntohl(iph->daddr);
nfo.loc_port = ntohs(tcph->dest);
nfo.rem_addr = ntohl(iph->saddr);
nfo.rem_port = ntohs(tcph->source);
- nes_debug(NES_DBG_CM, "Received packet: dest=" NIPQUAD_FMT
- ":0x%04X src=" NIPQUAD_FMT ":0x%04X\n",
- NIPQUAD(iph->daddr), tcph->dest,
- NIPQUAD(iph->saddr), tcph->source);
+ tmp_daddr = cpu_to_be32(iph->daddr);
+ tmp_saddr = cpu_to_be32(iph->saddr);
+
+ nes_debug(NES_DBG_CM, "Received packet: dest=%pI4:0x%04X src=%pI4:0x%04X\n",
+ &tmp_daddr, tcph->dest, &tmp_saddr, tcph->source);
do {
cm_node = find_node(cm_core,
/* Only type of packet accepted are for */
/* the PASSIVE open (syn only) */
if ((!tcph->syn) || (tcph->ack)) {
- cm_packets_dropped++;
+ skb_handled = 0;
break;
}
listener = find_listener(cm_core, nfo.loc_addr,
nfo.loc_port,
NES_CM_LISTENER_ACTIVE_STATE);
- if (listener) {
- nfo.cm_id = listener->cm_id;
- nfo.conn_type = listener->conn_type;
- } else {
- nes_debug(NES_DBG_CM, "Unable to find listener "
- "for the pkt\n");
- cm_packets_dropped++;
- dev_kfree_skb_any(skb);
+ if (!listener) {
+ nfo.cm_id = NULL;
+ nfo.conn_type = 0;
+ nes_debug(NES_DBG_CM, "Unable to find listener for the pkt\n");
+ skb_handled = 0;
break;
}
-
+ nfo.cm_id = listener->cm_id;
+ nfo.conn_type = listener->conn_type;
cm_node = make_cm_node(cm_core, nesvnic, &nfo,
listener);
if (!cm_node) {
dev_kfree_skb_any(skb);
break;
}
+ skb_reset_network_header(skb);
+ skb_set_transport_header(skb, sizeof(*tcph));
+ skb->len = ntohs(iph->tot_len);
process_packet(cm_node, skb, cm_core);
rem_ref_cm_node(cm_core, cm_node);
} while (0);
+ return skb_handled;
}
*/
static struct nes_cm_core *nes_cm_alloc_core(void)
{
- int i;
-
struct nes_cm_core *cm_core;
- struct sk_buff *skb = NULL;
/* setup the CM core */
/* alloc top level core control structure */
atomic_set(&cm_core->events_posted, 0);
- /* init the packet lists */
- skb_queue_head_init(&cm_core->tx_free_list);
-
- for (i = 0; i < NES_CM_DEFAULT_FRAME_CNT; i++) {
- skb = dev_alloc_skb(cm_core->mtu);
- if (!skb) {
- kfree(cm_core);
- return NULL;
- }
- /* add 'raw' skb to free frame list */
- skb_queue_head(&cm_core->tx_free_list, skb);
- }
-
cm_core->api = &nes_cm_api;
spin_lock_init(&cm_core->ht_lock);
sizeof(struct ietf_mpa_frame));
- /* notify OF layer that accept event was successfull */
+ /* notify OF layer that accept event was successful */
cm_id->add_ref(cm_id);
cm_event.event = IW_CM_EVENT_ESTABLISHED;
*/
int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)
{
+ int rc = 0;
cm_packets_received++;
if ((g_cm_core) && (g_cm_core->api)) {
- g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
+ rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
} else {
nes_debug(NES_DBG_CM, "Unable to process packet for CM,"
" cm is not setup properly.\n");
}
- return 0;
+ return rc;
}