net/rxrpc/peer_event.c

Source file repositories/reference/linux-study-clean/net/rxrpc/peer_event.c

File Facts

System
Linux kernel
Corpus path
net/rxrpc/peer_event.c
Extension
.c
Size
11959 bytes
Lines
459
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (serr->ee.ee_origin) {
		case SO_EE_ORIGIN_ICMP:
			memcpy(&srx->transport.sin.sin_addr,
			       skb_network_header(skb) + serr->addr_offset,
			       sizeof(struct in_addr));
			break;
		case SO_EE_ORIGIN_ICMP6:
			memcpy(&srx->transport.sin.sin_addr,
			       skb_network_header(skb) + serr->addr_offset + 12,
			       sizeof(struct in_addr));
			break;
		default:
			memcpy(&srx->transport.sin.sin_addr, &ip_hdr(skb)->saddr,
			       sizeof(struct in_addr));
			break;
		}
		break;

#ifdef CONFIG_AF_RXRPC_IPV6
	case AF_INET6:
		switch (serr->ee.ee_origin) {
		case SO_EE_ORIGIN_ICMP6:
			srx->transport.sin6.sin6_port = serr->port;
			memcpy(&srx->transport.sin6.sin6_addr,
			       skb_network_header(skb) + serr->addr_offset,
			       sizeof(struct in6_addr));
			break;
		case SO_EE_ORIGIN_ICMP:
			srx->transport_len = sizeof(srx->transport.sin);
			srx->transport.family = AF_INET;
			srx->transport.sin.sin_port = serr->port;
			memcpy(&srx->transport.sin.sin_addr,
			       skb_network_header(skb) + serr->addr_offset,
			       sizeof(struct in_addr));
			break;
		default:
			memcpy(&srx->transport.sin6.sin6_addr,
			       &ipv6_hdr(skb)->saddr,
			       sizeof(struct in6_addr));
			break;
		}
		break;
#endif

	default:
		BUG();
	}

	return rxrpc_lookup_peer_rcu(local, srx);
}

/*
 * Handle an MTU/fragmentation problem.
 */
static void rxrpc_adjust_mtu(struct rxrpc_peer *peer, unsigned int mtu)
{
	unsigned int max_data;

	/* wind down the local interface MTU */
	if (mtu > 0 && peer->if_mtu == 65535 && mtu < peer->if_mtu)
		peer->if_mtu = mtu;

	if (mtu == 0) {
		/* they didn't give us a size, estimate one */
		mtu = peer->if_mtu;
		if (mtu > 1500) {
			mtu >>= 1;
			if (mtu < 1500)
				mtu = 1500;
		} else {
			mtu -= 100;
			if (mtu < peer->hdrsize)
				mtu = peer->hdrsize + 4;
		}
	}

	max_data = max_t(int, mtu - peer->hdrsize, 500);
	if (max_data < peer->max_data) {
		if (peer->pmtud_good > max_data)
			peer->pmtud_good = max_data;
		if (peer->pmtud_bad > max_data + 1)
			peer->pmtud_bad = max_data + 1;

		trace_rxrpc_pmtud_reduce(peer, 0, max_data, rxrpc_pmtud_reduce_icmp);
		peer->max_data = max_data;
	}
}

/*
 * Handle an error received on the local endpoint.

Annotation

Implementation Notes