mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-01 22:54:01 +00:00
Merge branch 'dccp' of git://eden-feed.erg.abdn.ac.uk/net-next-2.6
This commit is contained in:
commit
98e684bd5c
7 changed files with 73 additions and 106 deletions
|
@ -165,8 +165,10 @@ enum {
|
|||
DCCPO_TIMESTAMP_ECHO = 42,
|
||||
DCCPO_ELAPSED_TIME = 43,
|
||||
DCCPO_MAX = 45,
|
||||
DCCPO_MIN_CCID_SPECIFIC = 128,
|
||||
DCCPO_MAX_CCID_SPECIFIC = 255,
|
||||
DCCPO_MIN_RX_CCID_SPECIFIC = 128, /* from sender to receiver */
|
||||
DCCPO_MAX_RX_CCID_SPECIFIC = 191,
|
||||
DCCPO_MIN_TX_CCID_SPECIFIC = 192, /* from receiver to sender */
|
||||
DCCPO_MAX_TX_CCID_SPECIFIC = 255,
|
||||
};
|
||||
/* maximum size of a single TLV-encoded DCCP option (sans type/len bytes) */
|
||||
#define DCCP_SINGLE_OPT_MAXLEN 253
|
||||
|
|
|
@ -62,18 +62,14 @@ struct ccid_operations {
|
|||
void (*ccid_hc_tx_exit)(struct sock *sk);
|
||||
void (*ccid_hc_rx_packet_recv)(struct sock *sk,
|
||||
struct sk_buff *skb);
|
||||
int (*ccid_hc_rx_parse_options)(struct sock *sk,
|
||||
unsigned char option,
|
||||
unsigned char len, u16 idx,
|
||||
unsigned char* value);
|
||||
int (*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
|
||||
u8 opt, u8 *val, u8 len);
|
||||
int (*ccid_hc_rx_insert_options)(struct sock *sk,
|
||||
struct sk_buff *skb);
|
||||
void (*ccid_hc_tx_packet_recv)(struct sock *sk,
|
||||
struct sk_buff *skb);
|
||||
int (*ccid_hc_tx_parse_options)(struct sock *sk,
|
||||
unsigned char option,
|
||||
unsigned char len, u16 idx,
|
||||
unsigned char* value);
|
||||
int (*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
|
||||
u8 opt, u8 *val, u8 len);
|
||||
int (*ccid_hc_tx_send_packet)(struct sock *sk,
|
||||
struct sk_buff *skb);
|
||||
void (*ccid_hc_tx_packet_sent)(struct sock *sk,
|
||||
|
@ -168,27 +164,31 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
|
|||
ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* ccid_hc_tx_parse_options - Parse CCID-specific options sent by the receiver
|
||||
* @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
|
||||
* @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
|
||||
* @val: value of @opt
|
||||
* @len: length of @val in bytes
|
||||
*/
|
||||
static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
|
||||
unsigned char option,
|
||||
unsigned char len, u16 idx,
|
||||
unsigned char* value)
|
||||
u8 pkt, u8 opt, u8 *val, u8 len)
|
||||
{
|
||||
int rc = 0;
|
||||
if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL)
|
||||
rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx,
|
||||
value);
|
||||
return rc;
|
||||
if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
|
||||
return 0;
|
||||
return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* ccid_hc_rx_parse_options - Parse CCID-specific options sent by the sender
|
||||
* Arguments are analogous to ccid_hc_tx_parse_options()
|
||||
*/
|
||||
static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
|
||||
unsigned char option,
|
||||
unsigned char len, u16 idx,
|
||||
unsigned char* value)
|
||||
u8 pkt, u8 opt, u8 *val, u8 len)
|
||||
{
|
||||
int rc = 0;
|
||||
if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL)
|
||||
rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value);
|
||||
return rc;
|
||||
if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
|
||||
return 0;
|
||||
return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
|
||||
}
|
||||
|
||||
static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
|
||||
|
|
|
@ -54,7 +54,6 @@ static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
|
|||
[TFRC_SSTATE_NO_SENT] = "NO_SENT",
|
||||
[TFRC_SSTATE_NO_FBACK] = "NO_FBACK",
|
||||
[TFRC_SSTATE_FBACK] = "FBACK",
|
||||
[TFRC_SSTATE_TERM] = "TERM",
|
||||
};
|
||||
|
||||
return ccid3_state_names[state];
|
||||
|
@ -208,10 +207,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
|
|||
ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk,
|
||||
ccid3_tx_state_name(hc->tx_state));
|
||||
|
||||
/* Ignore and do not restart after leaving the established state */
|
||||
if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN))
|
||||
goto out;
|
||||
|
||||
/* Reset feedback state to "no feedback received" */
|
||||
if (hc->tx_state == TFRC_SSTATE_FBACK)
|
||||
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
|
||||
else if (hc->tx_state != TFRC_SSTATE_NO_FBACK)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4
|
||||
|
@ -287,8 +289,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
|
|||
if (unlikely(skb->len == 0))
|
||||
return -EBADMSG;
|
||||
|
||||
switch (hc->tx_state) {
|
||||
case TFRC_SSTATE_NO_SENT:
|
||||
if (hc->tx_state == TFRC_SSTATE_NO_SENT) {
|
||||
sk_reset_timer(sk, &hc->tx_no_feedback_timer, (jiffies +
|
||||
usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
|
||||
hc->tx_last_win_count = 0;
|
||||
|
@ -323,9 +324,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
|
|||
ccid3_update_send_interval(hc);
|
||||
|
||||
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
|
||||
break;
|
||||
case TFRC_SSTATE_NO_FBACK:
|
||||
case TFRC_SSTATE_FBACK:
|
||||
|
||||
} else {
|
||||
delay = ktime_us_delta(hc->tx_t_nom, now);
|
||||
ccid3_pr_debug("delay=%ld\n", (long)delay);
|
||||
/*
|
||||
|
@ -340,10 +340,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
|
|||
return (u32)delay / USEC_PER_MSEC;
|
||||
|
||||
ccid3_hc_tx_update_win_count(hc, now);
|
||||
break;
|
||||
case TFRC_SSTATE_TERM:
|
||||
DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* prepare to send now (add options etc.) */
|
||||
|
@ -369,21 +365,15 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
|
|||
static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
|
||||
struct ccid3_options_received *opt_recv = &hc->tx_options_received;
|
||||
struct tfrc_tx_hist_entry *acked;
|
||||
ktime_t now;
|
||||
unsigned long t_nfb;
|
||||
u32 pinv, r_sample;
|
||||
u32 r_sample;
|
||||
|
||||
/* we are only interested in ACKs */
|
||||
if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||
|
||||
DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK))
|
||||
return;
|
||||
/* ... and only in the established state */
|
||||
if (hc->tx_state != TFRC_SSTATE_FBACK &&
|
||||
hc->tx_state != TFRC_SSTATE_NO_FBACK)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Locate the acknowledged packet in the TX history.
|
||||
*
|
||||
|
@ -403,17 +393,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|||
r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, acked->stamp));
|
||||
hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9);
|
||||
|
||||
/* Update receive rate in units of 64 * bytes/second */
|
||||
hc->tx_x_recv = opt_recv->ccid3or_receive_rate;
|
||||
hc->tx_x_recv <<= 6;
|
||||
|
||||
/* Update loss event rate (which is scaled by 1e6) */
|
||||
pinv = opt_recv->ccid3or_loss_event_rate;
|
||||
if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */
|
||||
hc->tx_p = 0;
|
||||
else /* can not exceed 100% */
|
||||
hc->tx_p = scaled_div(1, pinv);
|
||||
|
||||
/*
|
||||
* Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3
|
||||
*/
|
||||
|
@ -481,30 +460,36 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|||
jiffies + usecs_to_jiffies(t_nfb));
|
||||
}
|
||||
|
||||
static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
|
||||
unsigned char len, u16 idx,
|
||||
unsigned char *value)
|
||||
static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,
|
||||
u8 option, u8 *optval, u8 optlen)
|
||||
{
|
||||
struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
|
||||
struct ccid3_options_received *opt_recv = &hc->tx_options_received;
|
||||
__be32 opt_val;
|
||||
|
||||
switch (option) {
|
||||
case TFRC_OPT_RECEIVE_RATE:
|
||||
case TFRC_OPT_LOSS_EVENT_RATE:
|
||||
if (unlikely(len != 4)) {
|
||||
/* Must be ignored on Data packets, cf. RFC 4342 8.3 and 8.5 */
|
||||
if (packet_type == DCCP_PKT_DATA)
|
||||
break;
|
||||
if (unlikely(optlen != 4)) {
|
||||
DCCP_WARN("%s(%p), invalid len %d for %u\n",
|
||||
dccp_role(sk), sk, len, option);
|
||||
dccp_role(sk), sk, optlen, option);
|
||||
return -EINVAL;
|
||||
}
|
||||
opt_val = ntohl(get_unaligned((__be32 *)value));
|
||||
opt_val = ntohl(get_unaligned((__be32 *)optval));
|
||||
|
||||
if (option == TFRC_OPT_RECEIVE_RATE) {
|
||||
opt_recv->ccid3or_receive_rate = opt_val;
|
||||
/* Receive Rate is kept in units of 64 bytes/second */
|
||||
hc->tx_x_recv = opt_val;
|
||||
hc->tx_x_recv <<= 6;
|
||||
|
||||
ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
|
||||
dccp_role(sk), sk, opt_val);
|
||||
} else {
|
||||
opt_recv->ccid3or_loss_event_rate = opt_val;
|
||||
/* Update the fixpoint Loss Event Rate fraction */
|
||||
hc->tx_p = tfrc_invert_loss_event_rate(opt_val);
|
||||
|
||||
ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
|
||||
dccp_role(sk), sk, opt_val);
|
||||
}
|
||||
|
@ -527,9 +512,7 @@ static void ccid3_hc_tx_exit(struct sock *sk)
|
|||
{
|
||||
struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
|
||||
|
||||
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);
|
||||
sk_stop_timer(sk, &hc->tx_no_feedback_timer);
|
||||
|
||||
tfrc_tx_hist_purge(&hc->tx_hist);
|
||||
}
|
||||
|
||||
|
@ -588,7 +571,6 @@ static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
|
|||
static const char *const ccid3_rx_state_names[] = {
|
||||
[TFRC_RSTATE_NO_DATA] = "NO_DATA",
|
||||
[TFRC_RSTATE_DATA] = "DATA",
|
||||
[TFRC_RSTATE_TERM] = "TERM",
|
||||
};
|
||||
|
||||
return ccid3_rx_state_names[state];
|
||||
|
@ -614,14 +596,9 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk,
|
|||
{
|
||||
struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk);
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
ktime_t now;
|
||||
ktime_t now = ktime_get_real();
|
||||
s64 delta = 0;
|
||||
|
||||
if (unlikely(hc->rx_state == TFRC_RSTATE_TERM))
|
||||
return;
|
||||
|
||||
now = ktime_get_real();
|
||||
|
||||
switch (fbtype) {
|
||||
case CCID3_FBACK_INITIAL:
|
||||
hc->rx_x_recv = 0;
|
||||
|
@ -825,8 +802,6 @@ static void ccid3_hc_rx_exit(struct sock *sk)
|
|||
{
|
||||
struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk);
|
||||
|
||||
ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
|
||||
|
||||
tfrc_rx_hist_purge(&hc->rx_hist);
|
||||
tfrc_lh_cleanup(&hc->rx_li_hist);
|
||||
}
|
||||
|
@ -851,8 +826,7 @@ static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
|
|||
return -EINVAL;
|
||||
rx_info.tfrcrx_x_recv = hc->rx_x_recv;
|
||||
rx_info.tfrcrx_rtt = hc->rx_rtt;
|
||||
rx_info.tfrcrx_p = hc->rx_pinv == 0 ? ~0U :
|
||||
scaled_div(1, hc->rx_pinv);
|
||||
rx_info.tfrcrx_p = tfrc_invert_loss_event_rate(hc->rx_pinv);
|
||||
len = sizeof(rx_info);
|
||||
val = &rx_info;
|
||||
break;
|
||||
|
|
|
@ -67,17 +67,11 @@ enum ccid3_options {
|
|||
TFRC_OPT_RECEIVE_RATE = 194,
|
||||
};
|
||||
|
||||
struct ccid3_options_received {
|
||||
u32 ccid3or_loss_event_rate;
|
||||
u32 ccid3or_receive_rate;
|
||||
};
|
||||
|
||||
/* TFRC sender states */
|
||||
enum ccid3_hc_tx_states {
|
||||
TFRC_SSTATE_NO_SENT = 1,
|
||||
TFRC_SSTATE_NO_FBACK,
|
||||
TFRC_SSTATE_FBACK,
|
||||
TFRC_SSTATE_TERM,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -98,7 +92,6 @@ enum ccid3_hc_tx_states {
|
|||
* @tx_t_ld: Time last doubled during slow start
|
||||
* @tx_t_nom: Nominal send time of next packet
|
||||
* @tx_hist: Packet history
|
||||
* @tx_options_received: Parsed set of retrieved options
|
||||
*/
|
||||
struct ccid3_hc_tx_sock {
|
||||
u64 tx_x;
|
||||
|
@ -116,7 +109,6 @@ struct ccid3_hc_tx_sock {
|
|||
ktime_t tx_t_ld;
|
||||
ktime_t tx_t_nom;
|
||||
struct tfrc_tx_hist_entry *tx_hist;
|
||||
struct ccid3_options_received tx_options_received;
|
||||
};
|
||||
|
||||
static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
|
||||
|
@ -130,7 +122,6 @@ static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
|
|||
enum ccid3_hc_rx_states {
|
||||
TFRC_RSTATE_NO_DATA = 1,
|
||||
TFRC_RSTATE_DATA,
|
||||
TFRC_RSTATE_TERM = 127,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,6 +57,7 @@ static inline u32 tfrc_ewma(const u32 avg, const u32 newval, const u8 weight)
|
|||
|
||||
extern u32 tfrc_calc_x(u16 s, u32 R, u32 p);
|
||||
extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue);
|
||||
extern u32 tfrc_invert_loss_event_rate(u32 loss_event_rate);
|
||||
|
||||
extern int tfrc_tx_packet_history_init(void);
|
||||
extern void tfrc_tx_packet_history_exit(void);
|
||||
|
|
|
@ -687,3 +687,17 @@ u32 tfrc_calc_x_reverse_lookup(u32 fvalue)
|
|||
index = tfrc_binsearch(fvalue, 0);
|
||||
return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* tfrc_invert_loss_event_rate - Compute p so that 10^6 corresponds to 100%
|
||||
* When @loss_event_rate is large, there is a chance that p is truncated to 0.
|
||||
* To avoid re-entering slow-start in that case, we set p = TFRC_SMALLEST_P > 0.
|
||||
*/
|
||||
u32 tfrc_invert_loss_event_rate(u32 loss_event_rate)
|
||||
{
|
||||
if (loss_event_rate == UINT_MAX) /* see RFC 4342, 8.5 */
|
||||
return 0;
|
||||
if (unlikely(loss_event_rate == 0)) /* map 1/0 into 100% */
|
||||
return 1000000;
|
||||
return max_t(u32, scaled_div(1, loss_event_rate), TFRC_SMALLEST_P);
|
||||
}
|
||||
|
|
|
@ -96,18 +96,11 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
|
|||
}
|
||||
|
||||
/*
|
||||
* CCID-Specific Options (from RFC 4340, sec. 10.3):
|
||||
*
|
||||
* Option numbers 128 through 191 are for options sent from the
|
||||
* HC-Sender to the HC-Receiver; option numbers 192 through 255
|
||||
* are for options sent from the HC-Receiver to the HC-Sender.
|
||||
*
|
||||
* CCID-specific options are ignored during connection setup, as
|
||||
* negotiation may still be in progress (see RFC 4340, 10.3).
|
||||
* The same applies to Ack Vectors, as these depend on the CCID.
|
||||
*
|
||||
*/
|
||||
if (dreq != NULL && (opt >= 128 ||
|
||||
if (dreq != NULL && (opt >= DCCPO_MIN_RX_CCID_SPECIFIC ||
|
||||
opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1))
|
||||
goto ignore_option;
|
||||
|
||||
|
@ -226,23 +219,15 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
|
|||
dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
|
||||
dccp_role(sk), elapsed_time);
|
||||
break;
|
||||
case 128 ... 191: {
|
||||
const u16 idx = value - options;
|
||||
|
||||
case DCCPO_MIN_RX_CCID_SPECIFIC ... DCCPO_MAX_RX_CCID_SPECIFIC:
|
||||
if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
|
||||
opt, len, idx,
|
||||
value) != 0)
|
||||
pkt_type, opt, value, len))
|
||||
goto out_invalid_option;
|
||||
}
|
||||
break;
|
||||
case 192 ... 255: {
|
||||
const u16 idx = value - options;
|
||||
|
||||
case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC:
|
||||
if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
|
||||
opt, len, idx,
|
||||
value) != 0)
|
||||
pkt_type, opt, value, len))
|
||||
goto out_invalid_option;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DCCP_CRIT("DCCP(%p): option %d(len=%d) not "
|
||||
|
|
Loading…
Reference in a new issue