linux/net/dccp/ccid.h
<<
>>
Prefs
   1#ifndef _CCID_H
   2#define _CCID_H
   3/*
   4 *  net/dccp/ccid.h
   5 *
   6 *  An implementation of the DCCP protocol
   7 *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   8 *
   9 *  CCID infrastructure
  10 *
  11 *      This program is free software; you can redistribute it and/or modify it
  12 *      under the terms of the GNU General Public License version 2 as
  13 *      published by the Free Software Foundation.
  14 */
  15
  16#include <net/sock.h>
  17#include <linux/compiler.h>
  18#include <linux/dccp.h>
  19#include <linux/list.h>
  20#include <linux/module.h>
  21
  22/* maximum value for a CCID (RFC 4340, 19.5) */
  23#define CCID_MAX                255
  24#define CCID_SLAB_NAME_LENGTH   32
  25
  26struct tcp_info;
  27
  28/**
  29 *  struct ccid_operations  -  Interface to Congestion-Control Infrastructure
  30 *
  31 *  @ccid_id: numerical CCID ID (up to %CCID_MAX, cf. table 5 in RFC 4340, 10.)
  32 *  @ccid_ccmps: the CCMPS including network/transport headers (0 when disabled)
  33 *  @ccid_name: alphabetical identifier string for @ccid_id
  34 *  @ccid_hc_{r,t}x_slab: memory pool for the receiver/sender half-connection
  35 *  @ccid_hc_{r,t}x_obj_size: size of the receiver/sender half-connection socket
  36 *
  37 *  @ccid_hc_{r,t}x_init: CCID-specific initialisation routine (before startup)
  38 *  @ccid_hc_{r,t}x_exit: CCID-specific cleanup routine (before destruction)
  39 *  @ccid_hc_rx_packet_recv: implements the HC-receiver side
  40 *  @ccid_hc_{r,t}x_parse_options: parsing routine for CCID/HC-specific options
  41 *  @ccid_hc_{r,t}x_insert_options: insert routine for CCID/HC-specific options
  42 *  @ccid_hc_tx_packet_recv: implements feedback processing for the HC-sender
  43 *  @ccid_hc_tx_send_packet: implements the sending part of the HC-sender
  44 *  @ccid_hc_tx_packet_sent: does accounting for packets in flight by HC-sender
  45 *  @ccid_hc_{r,t}x_get_info: INET_DIAG information for HC-receiver/sender
  46 *  @ccid_hc_{r,t}x_getsockopt: socket options specific to HC-receiver/sender
  47 */
  48struct ccid_operations {
  49        unsigned char           ccid_id;
  50        __u32                   ccid_ccmps;
  51        const char              *ccid_name;
  52        struct kmem_cache       *ccid_hc_rx_slab,
  53                                *ccid_hc_tx_slab;
  54        char                    ccid_hc_rx_slab_name[CCID_SLAB_NAME_LENGTH];
  55        char                    ccid_hc_tx_slab_name[CCID_SLAB_NAME_LENGTH];
  56        __u32                   ccid_hc_rx_obj_size,
  57                                ccid_hc_tx_obj_size;
  58        /* Interface Routines */
  59        int             (*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
  60        int             (*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk);
  61        void            (*ccid_hc_rx_exit)(struct sock *sk);
  62        void            (*ccid_hc_tx_exit)(struct sock *sk);
  63        void            (*ccid_hc_rx_packet_recv)(struct sock *sk,
  64                                                  struct sk_buff *skb);
  65        int             (*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
  66                                                    u8 opt, u8 *val, u8 len);
  67        int             (*ccid_hc_rx_insert_options)(struct sock *sk,
  68                                                     struct sk_buff *skb);
  69        void            (*ccid_hc_tx_packet_recv)(struct sock *sk,
  70                                                  struct sk_buff *skb);
  71        int             (*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
  72                                                    u8 opt, u8 *val, u8 len);
  73        int             (*ccid_hc_tx_send_packet)(struct sock *sk,
  74                                                  struct sk_buff *skb);
  75        void            (*ccid_hc_tx_packet_sent)(struct sock *sk,
  76                                                  unsigned int len);
  77        void            (*ccid_hc_rx_get_info)(struct sock *sk,
  78                                               struct tcp_info *info);
  79        void            (*ccid_hc_tx_get_info)(struct sock *sk,
  80                                               struct tcp_info *info);
  81        int             (*ccid_hc_rx_getsockopt)(struct sock *sk,
  82                                                 const int optname, int len,
  83                                                 u32 __user *optval,
  84                                                 int __user *optlen);
  85        int             (*ccid_hc_tx_getsockopt)(struct sock *sk,
  86                                                 const int optname, int len,
  87                                                 u32 __user *optval,
  88                                                 int __user *optlen);
  89};
  90
  91extern struct ccid_operations ccid2_ops;
  92#ifdef CONFIG_IP_DCCP_CCID3
  93extern struct ccid_operations ccid3_ops;
  94#endif
  95
  96extern int  ccid_initialize_builtins(void);
  97extern void ccid_cleanup_builtins(void);
  98
  99struct ccid {
 100        struct ccid_operations *ccid_ops;
 101        char                   ccid_priv[0];
 102};
 103
 104static inline void *ccid_priv(const struct ccid *ccid)
 105{
 106        return (void *)ccid->ccid_priv;
 107}
 108
 109extern bool ccid_support_check(u8 const *ccid_array, u8 array_len);
 110extern int  ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
 111extern int  ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
 112                                          char __user *, int __user *);
 113
 114extern struct ccid *ccid_new(const u8 id, struct sock *sk, bool rx);
 115
 116static inline int ccid_get_current_rx_ccid(struct dccp_sock *dp)
 117{
 118        struct ccid *ccid = dp->dccps_hc_rx_ccid;
 119
 120        if (ccid == NULL || ccid->ccid_ops == NULL)
 121                return -1;
 122        return ccid->ccid_ops->ccid_id;
 123}
 124
 125static inline int ccid_get_current_tx_ccid(struct dccp_sock *dp)
 126{
 127        struct ccid *ccid = dp->dccps_hc_tx_ccid;
 128
 129        if (ccid == NULL || ccid->ccid_ops == NULL)
 130                return -1;
 131        return ccid->ccid_ops->ccid_id;
 132}
 133
 134extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
 135extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
 136
 137/*
 138 * Congestion control of queued data packets via CCID decision.
 139 *
 140 * The TX CCID performs its congestion-control by indicating whether and when a
 141 * queued packet may be sent, using the return code of ccid_hc_tx_send_packet().
 142 * The following modes are supported via the symbolic constants below:
 143 * - timer-based pacing    (CCID returns a delay value in milliseconds);
 144 * - autonomous dequeueing (CCID internally schedules dccps_xmitlet).
 145 */
 146
 147enum ccid_dequeueing_decision {
 148        CCID_PACKET_SEND_AT_ONCE =       0x00000,  /* "green light": no delay */
 149        CCID_PACKET_DELAY_MAX =          0x0FFFF,  /* maximum delay in msecs  */
 150        CCID_PACKET_DELAY =              0x10000,  /* CCID msec-delay mode */
 151        CCID_PACKET_WILL_DEQUEUE_LATER = 0x20000,  /* CCID autonomous mode */
 152        CCID_PACKET_ERR =                0xF0000,  /* error condition */
 153};
 154
 155static inline int ccid_packet_dequeue_eval(const int return_code)
 156{
 157        if (return_code < 0)
 158                return CCID_PACKET_ERR;
 159        if (return_code == 0)
 160                return CCID_PACKET_SEND_AT_ONCE;
 161        if (return_code <= CCID_PACKET_DELAY_MAX)
 162                return CCID_PACKET_DELAY;
 163        return return_code;
 164}
 165
 166static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
 167                                         struct sk_buff *skb)
 168{
 169        if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
 170                return ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb);
 171        return CCID_PACKET_SEND_AT_ONCE;
 172}
 173
 174static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
 175                                          unsigned int len)
 176{
 177        if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
 178                ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, len);
 179}
 180
 181static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
 182                                          struct sk_buff *skb)
 183{
 184        if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
 185                ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb);
 186}
 187
 188static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
 189                                          struct sk_buff *skb)
 190{
 191        if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
 192                ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
 193}
 194
 195/**
 196 * ccid_hc_tx_parse_options  -  Parse CCID-specific options sent by the receiver
 197 * @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
 198 * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
 199 * @val: value of @opt
 200 * @len: length of @val in bytes
 201 */
 202static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
 203                                           u8 pkt, u8 opt, u8 *val, u8 len)
 204{
 205        if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
 206                return 0;
 207        return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
 208}
 209
 210/**
 211 * ccid_hc_rx_parse_options  -  Parse CCID-specific options sent by the sender
 212 * Arguments are analogous to ccid_hc_tx_parse_options()
 213 */
 214static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
 215                                           u8 pkt, u8 opt, u8 *val, u8 len)
 216{
 217        if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
 218                return 0;
 219        return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
 220}
 221
 222static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
 223                                            struct sk_buff *skb)
 224{
 225        if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
 226                return ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
 227        return 0;
 228}
 229
 230static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
 231                                       struct tcp_info *info)
 232{
 233        if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
 234                ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
 235}
 236
 237static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
 238                                       struct tcp_info *info)
 239{
 240        if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
 241                ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
 242}
 243
 244static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
 245                                        const int optname, int len,
 246                                        u32 __user *optval, int __user *optlen)
 247{
 248        int rc = -ENOPROTOOPT;
 249        if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
 250                rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
 251                                                 optval, optlen);
 252        return rc;
 253}
 254
 255static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
 256                                        const int optname, int len,
 257                                        u32 __user *optval, int __user *optlen)
 258{
 259        int rc = -ENOPROTOOPT;
 260        if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
 261                rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
 262                                                 optval, optlen);
 263        return rc;
 264}
 265#endif /* _CCID_H */
 266