/drivers/infiniband/hw/nes/nes_cm.c
C | 3691 lines | 2842 code | 524 blank | 325 comment | 358 complexity | 59376caec3b2af1b2fa625e2df5cd44b MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
- #define TCPOPT_TIMESTAMP 8
- #include <asm/atomic.h>
- #include <linux/skbuff.h>
- #include <linux/ip.h>
- #include <linux/tcp.h>
- #include <linux/init.h>
- #include <linux/if_arp.h>
- #include <linux/if_vlan.h>
- #include <linux/notifier.h>
- #include <linux/net.h>
- #include <linux/types.h>
- #include <linux/timer.h>
- #include <linux/time.h>
- #include <linux/delay.h>
- #include <linux/etherdevice.h>
- #include <linux/netdevice.h>
- #include <linux/random.h>
- #include <linux/list.h>
- #include <linux/threads.h>
- #include <linux/highmem.h>
- #include <linux/slab.h>
- #include <net/arp.h>
- #include <net/neighbour.h>
- #include <net/route.h>
- #include <net/ip_fib.h>
- #include <net/tcp.h>
- #include "nes.h"
- u32 cm_packets_sent;
- u32 cm_packets_bounced;
- u32 cm_packets_dropped;
- u32 cm_packets_retrans;
- u32 cm_packets_created;
- u32 cm_packets_received;
- atomic_t cm_listens_created;
- atomic_t cm_listens_destroyed;
- u32 cm_backlog_drops;
- atomic_t cm_loopbacks;
- atomic_t cm_nodes_created;
- atomic_t cm_nodes_destroyed;
- atomic_t cm_accel_dropped_pkts;
- atomic_t cm_resets_recvd;
- static inline int mini_cm_accelerated(struct nes_cm_core *,
- struct nes_cm_node *);
- static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
- struct nes_vnic *, struct nes_cm_info *);
- static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
- static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *,
- struct nes_vnic *, u16, void *, struct nes_cm_info *);
- static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
- static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
- static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
- 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 void form_cm_frame(struct sk_buff *, struct nes_cm_node *,
- void *, u32, void *, u32, u8);
- static int add_ref_cm_node(struct nes_cm_node *);
- static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
- static int nes_cm_disconn_true(struct nes_qp *);
- static int nes_cm_post_event(struct nes_cm_event *event);
- static int nes_disconnect(struct nes_qp *nesqp, int abrupt);
- static void nes_disconnect_worker(struct work_struct *work);
- static int send_mpa_request(struct nes_cm_node *, struct sk_buff *);
- static int send_mpa_reject(struct nes_cm_node *);
- static int send_syn(struct nes_cm_node *, u32, struct sk_buff *);
- static int send_reset(struct nes_cm_node *, struct sk_buff *);
- static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);
- static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb);
- static void process_packet(struct nes_cm_node *, struct sk_buff *,
- struct nes_cm_core *);
- static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);
- static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);
- static void cleanup_retrans_entry(struct nes_cm_node *);
- static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *);
- static void free_retrans_entry(struct nes_cm_node *cm_node);
- static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
- struct sk_buff *skb, int optionsize, int passive);
- /* CM event handler functions */
- static void cm_event_connected(struct nes_cm_event *);
- static void cm_event_connect_error(struct nes_cm_event *);
- static void cm_event_reset(struct nes_cm_event *);
- static void cm_event_mpa_req(struct nes_cm_event *);
- static void cm_event_mpa_reject(struct nes_cm_event *);
- static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node);
- static void print_core(struct nes_cm_core *core);
- /* External CM API Interface */
- /* instance of function pointers for client API */
- /* set address of this instance to cm_core->cm_ops at cm_core alloc */
- static struct nes_cm_ops nes_cm_api = {
- mini_cm_accelerated,
- mini_cm_listen,
- mini_cm_del_listen,
- mini_cm_connect,
- mini_cm_close,
- mini_cm_accept,
- mini_cm_reject,
- mini_cm_recv_pkt,
- mini_cm_dealloc_core,
- mini_cm_get,
- mini_cm_set
- };
- static struct nes_cm_core *g_cm_core;
- atomic_t cm_connects;
- atomic_t cm_accepts;
- atomic_t cm_disconnects;
- atomic_t cm_closes;
- atomic_t cm_connecteds;
- atomic_t cm_connect_reqs;
- atomic_t cm_rejects;
- /**
- * create_event
- */
- static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
- enum nes_cm_event_type type)
- {
- struct nes_cm_event *event;
- if (!cm_node->cm_id)
- return NULL;
- /* allocate an empty event */
- event = kzalloc(sizeof(*event), GFP_ATOMIC);
- if (!event)
- return NULL;
- event->type = type;
- event->cm_node = cm_node;
- event->cm_info.rem_addr = cm_node->rem_addr;
- event->cm_info.loc_addr = cm_node->loc_addr;
- event->cm_info.rem_port = cm_node->rem_port;
- event->cm_info.loc_port = cm_node->loc_port;
- event->cm_info.cm_id = cm_node->cm_id;
- nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, "
- "dst_addr=%08x[%x], src_addr=%08x[%x]\n",
- cm_node, event, type, event->cm_info.loc_addr,
- event->cm_info.loc_port, event->cm_info.rem_addr,
- event->cm_info.rem_port);
- nes_cm_post_event(event);
- return event;
- }
- /**
- * send_mpa_request
- */
- static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
- {
- if (!skb) {
- nes_debug(NES_DBG_CM, "skb set to NULL\n");
- return -1;
- }
- /* send an MPA Request frame */
- form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
- cm_node->mpa_frame_size, SET_ACK);
- return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
- }
- static int send_mpa_reject(struct nes_cm_node *cm_node)
- {
- struct sk_buff *skb = NULL;
- skb = dev_alloc_skb(MAX_CM_BUFFER);
- if (!skb) {
- nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
- return -ENOMEM;
- }
- /* send an MPA reject frame */
- form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
- cm_node->mpa_frame_size, SET_ACK | SET_FIN);
- cm_node->state = NES_CM_STATE_FIN_WAIT1;
- return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
- }
- /**
- * recv_mpa - process a received TCP pkt, we are expecting an
- * IETF MPA frame
- */
- static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
- u32 len)
- {
- struct ietf_mpa_frame *mpa_frame;
- *type = NES_MPA_REQUEST_ACCEPT;
-