// SPDX-License-Identifier: GPL-2.0-or-later /* Peer event handling, typically ICMP messages. * * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com)
*/
/* 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;
if (keepalive_at <= base ||
keepalive_at > base + RXRPC_KEEPALIVE_TIME) {
rxrpc_send_keepalive(peer);
slot = RXRPC_KEEPALIVE_TIME;
}
/* A transmission to this peer occurred since last we * examined it so put it into the appropriate future * bucket.
*/
slot += cursor;
slot &= mask;
spin_lock_bh(&rxnet->peer_hash_lock);
list_add_tail(&peer->keepalive_link,
&rxnet->peer_keepalive[slot & mask]);
spin_unlock_bh(&rxnet->peer_hash_lock);
rxrpc_unuse_local(peer->local, rxrpc_local_unuse_peer_keepalive);
}
rxrpc_put_peer(peer, rxrpc_peer_put_keepalive);
spin_lock_bh(&rxnet->peer_hash_lock);
}
now = ktime_get_seconds();
base = rxnet->peer_keepalive_base;
cursor = rxnet->peer_keepalive_cursor;
_enter("%lld,%u", base - now, cursor);
if (!rxnet->live) return;
/* Remove to a temporary list all the peers that are currently lodged * in expired buckets plus all new peers. * * Everything in the bucket at the cursor is processed this * second; the bucket at cursor + 1 goes at now + 1s and so * on...
*/
spin_lock_bh(&rxnet->peer_hash_lock);
list_splice_init(&rxnet->peer_keepalive_new, &collector);
/* Schedule the timer for the next occupied timeslot. */
cursor = rxnet->peer_keepalive_cursor;
stop = cursor + RXRPC_KEEPALIVE_TIME - 1; for (; (s8)(cursor - stop) < 0; cursor++) { if (!list_empty(&rxnet->peer_keepalive[cursor & mask])) break;
base++;
}
now = ktime_get_seconds();
delay = base - now; if (delay < 1)
delay = 1;
delay *= HZ; if (rxnet->live)
timer_reduce(&rxnet->peer_keepalive_timer, jiffies + delay);
_leave("");
}
/* * Do path MTU probing.
*/ void rxrpc_input_probe_for_pmtud(struct rxrpc_connection *conn, rxrpc_serial_t acked_serial, bool sendmsg_fail)
{ struct rxrpc_peer *peer = conn->peer; unsignedint max_data = peer->max_data; int good, trial, bad, jumbo;
good = peer->pmtud_good;
trial = peer->pmtud_trial;
bad = peer->pmtud_bad; if (good >= bad - 1) {
conn->pmtud_probe = 0;
peer->pmtud_lost = false; return;
}
if (!peer->pmtud_probing) goto send_probe;
if (sendmsg_fail || after(acked_serial, conn->pmtud_probe)) { /* Retry a lost probe. */ if (!peer->pmtud_lost) {
trace_rxrpc_pmtud_lost(conn, acked_serial);
conn->pmtud_probe = 0;
peer->pmtud_lost = true; goto send_probe;
}
/* The probed size didn't seem to get through. */
bad = trial;
peer->pmtud_bad = bad; if (bad <= max_data)
max_data = bad - 1;
} else { /* It did get through. */
good = trial;
peer->pmtud_good = good; if (good > max_data)
max_data = good;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.