void rxrpc_reject_packets(struct work_struct *work) { union { struct sockaddr sa; struct sockaddr_in sin; } sa; struct rxrpc_skb_priv *sp; struct rxrpc_header hdr; struct rxrpc_local *local; struct sk_buff *skb; struct msghdr msg; struct kvec iov[2]; size_t size; __be32 code; local = container_of(work, struct rxrpc_local, rejecter); rxrpc_get_local(local); _enter("%d", local->debug_id); iov[0].iov_base = &hdr; iov[0].iov_len = sizeof(hdr); iov[1].iov_base = &code; iov[1].iov_len = sizeof(code); size = sizeof(hdr) + sizeof(code); msg.msg_name = &sa; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; memset(&sa, 0, sizeof(sa)); sa.sa.sa_family = local->srx.transport.family; switch (sa.sa.sa_family) { case AF_INET: msg.msg_namelen = sizeof(sa.sin); break; default: msg.msg_namelen = 0; break; } memset(&hdr, 0, sizeof(hdr)); hdr.type = RXRPC_PACKET_TYPE_ABORT; while ((skb = skb_dequeue(&local->reject_queue))) { sp = rxrpc_skb(skb); switch (sa.sa.sa_family) { case AF_INET: sa.sin.sin_port = udp_hdr(skb)->source; sa.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; code = htonl(skb->priority); hdr.epoch = sp->hdr.epoch; hdr.cid = sp->hdr.cid; hdr.callNumber = sp->hdr.callNumber; hdr.serviceId = sp->hdr.serviceId; hdr.flags = sp->hdr.flags; hdr.flags ^= RXRPC_CLIENT_INITIATED; hdr.flags &= RXRPC_CLIENT_INITIATED; kernel_sendmsg(local->socket, &msg, iov, 2, size); break; default: break; } rxrpc_free_skb(skb); rxrpc_put_local(local); } rxrpc_put_local(local); _leave(""); }
/* * Allocate a new incoming call from the prealloc pool, along with a connection * and a peer as necessary. */ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx, struct rxrpc_local *local, struct rxrpc_connection *conn, struct sk_buff *skb) { struct rxrpc_backlog *b = rx->backlog; struct rxrpc_peer *peer, *xpeer; struct rxrpc_call *call; unsigned short call_head, conn_head, peer_head; unsigned short call_tail, conn_tail, peer_tail; unsigned short call_count, conn_count; /* #calls >= #conns >= #peers must hold true. */ call_head = smp_load_acquire(&b->call_backlog_head); call_tail = b->call_backlog_tail; call_count = CIRC_CNT(call_head, call_tail, RXRPC_BACKLOG_MAX); conn_head = smp_load_acquire(&b->conn_backlog_head); conn_tail = b->conn_backlog_tail; conn_count = CIRC_CNT(conn_head, conn_tail, RXRPC_BACKLOG_MAX); ASSERTCMP(conn_count, >=, call_count); peer_head = smp_load_acquire(&b->peer_backlog_head); peer_tail = b->peer_backlog_tail; ASSERTCMP(CIRC_CNT(peer_head, peer_tail, RXRPC_BACKLOG_MAX), >=, conn_count); if (call_count == 0) return NULL; if (!conn) { /* No connection. We're going to need a peer to start off * with. If one doesn't yet exist, use a spare from the * preallocation set. We dump the address into the spare in * anticipation - and to save on stack space. */ xpeer = b->peer_backlog[peer_tail]; if (rxrpc_extract_addr_from_skb(&xpeer->srx, skb) < 0) return NULL; peer = rxrpc_lookup_incoming_peer(local, xpeer); if (peer == xpeer) { b->peer_backlog[peer_tail] = NULL; smp_store_release(&b->peer_backlog_tail, (peer_tail + 1) & (RXRPC_BACKLOG_MAX - 1)); } /* Now allocate and set up the connection */ conn = b->conn_backlog[conn_tail]; b->conn_backlog[conn_tail] = NULL; smp_store_release(&b->conn_backlog_tail, (conn_tail + 1) & (RXRPC_BACKLOG_MAX - 1)); rxrpc_get_local(local); conn->params.local = local; conn->params.peer = peer; rxrpc_see_connection(conn); rxrpc_new_incoming_connection(rx, conn, skb); } else { rxrpc_get_connection(conn); } /* And now we can allocate and set up a new call */ call = b->call_backlog[call_tail]; b->call_backlog[call_tail] = NULL; smp_store_release(&b->call_backlog_tail, (call_tail + 1) & (RXRPC_BACKLOG_MAX - 1)); rxrpc_see_call(call); call->conn = conn; call->peer = rxrpc_get_peer(conn->params.peer); call->cong_cwnd = call->peer->cong_cwnd; return call; }