The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/tcp_hpts.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016-2018 Netflix Inc.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  *
   25  * $FreeBSD: releng/12.0/sys/netinet/tcp_hpts.h 335924 2018-07-04 02:47:16Z mmacy $
   26  */
   27 
   28 #ifndef __tcp_hpts_h__
   29 #define __tcp_hpts_h__
   30 
   31 /*
   32  * The hpts uses a 102400 wheel. The wheel
   33  * defines the time in 10 usec increments (102400 x 10).
   34  * This gives a range of 10usec - 1024ms to place
   35  * an entry within. If the user requests more than
   36  * 1.024 second, a remaineder is attached and the hpts
   37  * when seeing the remainder will re-insert the
   38  * inpcb forward in time from where it is until
   39  * the remainder is zero.
   40  */
   41 
   42 #define NUM_OF_HPTSI_SLOTS 102400
   43 
   44 TAILQ_HEAD(hptsh, inpcb);
   45 
   46 /* Number of useconds in a hpts tick */
   47 #define HPTS_TICKS_PER_USEC 10
   48 #define HPTS_MS_TO_SLOTS(x) (x * 100)
   49 #define HPTS_USEC_TO_SLOTS(x) ((x+9) /10)
   50 #define HPTS_USEC_IN_SEC 1000000
   51 #define HPTS_MSEC_IN_SEC 1000
   52 #define HPTS_USEC_IN_MSEC 1000
   53 
   54 #define DEFAULT_HPTS_LOG 3072
   55 
   56 /*
   57  * Log flags consist of
   58  *  7f      7f         1            1 bits
   59  * p_cpu | p_num | INPUT_ACTIVE | HPTS_ACTIVE
   60  *
   61  * So for example cpu 10, number 10 would with
   62  * input active would show up as:
   63  * p_flags = 0001010 0001010 1 0
   64  *  <or>
   65  * p_flags = 0x142a
   66  */
   67 #define HPTS_HPTS_ACTIVE 0x01
   68 #define HPTS_INPUT_ACTIVE 0x02
   69 
   70 #define HPTSLOG_IMMEDIATE       1
   71 #define HPTSLOG_INSERT_NORMAL   2
   72 #define HPTSLOG_INSERT_SLEEPER  3
   73 #define HPTSLOG_SLEEP_AFTER     4
   74 #define HPTSLOG_SLEEP_BEFORE    5
   75 #define HPTSLOG_INSERTED        6
   76 #define HPTSLOG_WAKEUP_HPTS     7
   77 #define HPTSLOG_SETTORUN        8
   78 #define HPTSLOG_HPTSI           9
   79 #define HPTSLOG_TOLONG          10
   80 #define HPTSLOG_AWAKENS 11
   81 #define HPTSLOG_TIMESOUT        12
   82 #define HPTSLOG_SLEEPSET        13
   83 #define HPTSLOG_WAKEUP_INPUT    14
   84 #define HPTSLOG_RESCHEDULE     15
   85 #define HPTSLOG_AWAKE           16
   86 #define HPTSLOG_INP_DONE        17
   87 
   88 struct hpts_log {
   89         struct inpcb *inp;
   90         int32_t event;
   91         uint32_t cts;
   92         int32_t line;
   93         uint32_t ticknow;
   94         uint32_t t_paceslot;
   95         uint32_t t_hptsreq;
   96         uint32_t p_curtick;
   97         uint32_t p_prevtick;
   98         uint32_t slot_req;
   99         uint32_t p_on_queue_cnt;
  100         uint32_t p_nxt_slot;
  101         uint32_t p_cur_slot;
  102         uint32_t p_hpts_sleep_time;
  103         uint16_t p_flags;
  104         uint8_t p_onhpts;
  105         uint8_t p_oninput;
  106         uint8_t is_notempty;
  107 };
  108 
  109 struct hpts_diag {
  110         uint32_t p_hpts_active;
  111         uint32_t p_nxt_slot;
  112         uint32_t p_cur_slot;
  113         uint32_t slot_req;
  114         uint32_t inp_hptsslot;
  115         uint32_t slot_now;
  116         uint32_t have_slept;
  117         uint32_t hpts_sleep_time;
  118         uint32_t yet_to_sleep;
  119         uint32_t need_new_to;
  120         int32_t co_ret;
  121         uint8_t p_on_min_sleep;
  122 };
  123 
  124 #ifdef _KERNEL
  125 /* Each hpts has its own p_mtx which is used for locking */
  126 struct tcp_hpts_entry {
  127         /* Cache line 0x00 */
  128         struct mtx p_mtx;       /* Mutex for hpts */
  129         uint32_t p_hpts_active; /* Flag that says hpts is awake  */
  130         uint32_t p_curtick;     /* Current tick in 10 us the hpts is at */
  131         uint32_t p_prevtick;    /* Previous tick in 10 us the hpts ran */
  132         uint32_t p_cur_slot;    /* Current slot in wheel hpts is draining */
  133         uint32_t p_nxt_slot;    /* The next slot outside the current range of
  134                                  * slots that the hpts is running on. */
  135         int32_t p_on_queue_cnt; /* Count on queue in this hpts */
  136         uint32_t enobuf_cnt;
  137         uint16_t p_log_at;
  138         uint8_t p_direct_wake :1, /* boolean */
  139                 p_log_wrapped :1, /* boolean */
  140                 p_on_min_sleep:1; /* boolean */
  141         uint8_t p_fill;
  142         /* Cache line 0x40 */
  143         void *p_inp;
  144         struct hptsh p_input;   /* For the tcp-input runner */
  145         /* Hptsi wheel */
  146         struct hptsh *p_hptss;
  147         struct hpts_log *p_log;
  148         uint32_t p_logsize;
  149         int32_t p_on_inqueue_cnt; /* Count on input queue in this hpts */
  150         uint32_t hit_no_enobuf;
  151         uint32_t p_dyn_adjust;
  152         uint32_t p_hpts_sleep_time;     /* Current sleep interval having a max
  153                                          * of 255ms */
  154         uint32_t p_delayed_by;  /* How much were we delayed by */
  155         /* Cache line 0x80 */
  156         struct sysctl_ctx_list hpts_ctx;
  157         struct sysctl_oid *hpts_root;
  158         struct intr_event *ie;
  159         void *ie_cookie;
  160         uint16_t p_num;         /* The hpts number one per cpu */
  161         uint16_t p_cpu;         /* The hpts CPU */
  162         /* There is extra space in here */
  163         /* Cache line 0x100 */
  164         struct callout co __aligned(CACHE_LINE_SIZE);
  165 }               __aligned(CACHE_LINE_SIZE);
  166 
  167 struct tcp_hptsi {
  168         struct proc *rp_proc;   /* Process structure for hpts */
  169         struct tcp_hpts_entry **rp_ent; /* Array of hptss */
  170         uint32_t rp_num_hptss;  /* Number of hpts threads */
  171 };
  172 
  173 #endif
  174 
  175 #define HPTS_REMOVE_INPUT  0x01
  176 #define HPTS_REMOVE_OUTPUT 0x02
  177 #define HPTS_REMOVE_ALL    (HPTS_REMOVE_INPUT | HPTS_REMOVE_OUTPUT)
  178 
  179 /*
  180  * When using the hpts, a TCP stack must make sure
  181  * that once a INP_DROPPED flag is applied to a INP
  182  * that it does not expect tcp_output() to ever be
  183  * called by the hpts. The hpts will *not* call
  184  * any output (or input) functions on a TCB that
  185  * is in the DROPPED state.
  186  *
  187  * This implies final ACK's and RST's that might
  188  * be sent when a TCB is still around must be
  189  * sent from a routine like tcp_respond().
  190  */
  191 #define DEFAULT_MIN_SLEEP 250   /* How many usec's is default for hpts sleep
  192                                  * this determines min granularity of the
  193                                  * hpts. If 0, granularity is 10useconds at
  194                                  * the cost of more CPU (context switching). */
  195 #ifdef _KERNEL
  196 #define HPTS_MTX_ASSERT(hpts) mtx_assert(&(hpts)->p_mtx, MA_OWNED)
  197 struct tcp_hpts_entry *tcp_hpts_lock(struct inpcb *inp);
  198 struct tcp_hpts_entry *tcp_input_lock(struct inpcb *inp);
  199 int __tcp_queue_to_hpts_immediate(struct inpcb *inp, int32_t line);
  200 #define tcp_queue_to_hpts_immediate(a)__tcp_queue_to_hpts_immediate(a, __LINE__)
  201 
  202 struct tcp_hpts_entry *tcp_cur_hpts(struct inpcb *inp);
  203 #define tcp_hpts_remove(a, b) __tcp_hpts_remove(a, b, __LINE__)
  204 void __tcp_hpts_remove(struct inpcb *inp, int32_t flags, int32_t line);
  205 
  206 /*
  207  * To insert a TCB on the hpts you *must* be holding the
  208  * INP_WLOCK(). The hpts insert code will then acqurire
  209  * the hpts's lock and insert the TCB on the requested
  210  * slot possibly waking up the hpts if you are requesting
  211  * a time earlier than what the hpts is sleeping to (if
  212  * the hpts is sleeping). You may check the inp->inp_in_hpts
  213  * flag without the hpts lock. The hpts is the only one
  214  * that will clear this flag holding only the hpts lock. This
  215  * means that in your tcp_output() routine when you test for
  216  * it to be 1 (so you wont call output) it may be transitioning
  217  * to 0 (by the hpts). That will be fine since that will just
  218  * mean an extra call to tcp_output that most likely will find
  219  * the call you executed (when the mis-match occured) will have
  220  * put the TCB back on the hpts and it will return. If your
  221  * call did not add it back to the hpts then you will either
  222  * over-send or the cwnd will block you from sending more.
  223  *
  224  * Note you should also be holding the INP_WLOCK() when you
  225  * call the remove from the hpts as well. Thoug usually
  226  * you are either doing this from a timer, where you need
  227  * that INP_WLOCK() or from destroying your TCB where again
  228  * you should already have the INP_WLOCK().
  229  */
  230 uint32_t __tcp_hpts_insert(struct inpcb *inp, uint32_t slot, int32_t line);
  231 #define tcp_hpts_insert(a, b) __tcp_hpts_insert(a, b, __LINE__)
  232 
  233 uint32_t
  234 tcp_hpts_insert_diag(struct inpcb *inp, uint32_t slot, int32_t line, struct hpts_diag *diag);
  235 
  236 int
  237     __tcp_queue_to_input_locked(struct inpcb *inp, struct tcp_hpts_entry *hpts, int32_t line);
  238 #define tcp_queue_to_input_locked(a, b) __tcp_queue_to_input_locked(a, b, __LINE__);
  239 void
  240 tcp_queue_pkt_to_input(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
  241     int32_t tlen, int32_t drop_hdrlen, uint8_t iptos);
  242 int
  243 __tcp_queue_to_input(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
  244     int32_t tlen, int32_t drop_hdrlen, uint8_t iptos, int32_t line);
  245 #define tcp_queue_to_input(a, b, c, d, e, f, g) __tcp_queue_to_input(a, b, c, d, e, f, g, __LINE__)
  246 
  247 uint16_t tcp_hpts_delayedby(struct inpcb *inp);
  248 
  249 void __tcp_set_hpts(struct inpcb *inp, int32_t line);
  250 #define tcp_set_hpts(a) __tcp_set_hpts(a, __LINE__)
  251 
  252 void __tcp_set_inp_to_drop(struct inpcb *inp, uint16_t reason, int32_t line);
  253 #define tcp_set_inp_to_drop(a, b) __tcp_set_inp_to_drop(a, b, __LINE__)
  254 
  255 extern int32_t tcp_min_hptsi_time;
  256 
  257 static __inline uint32_t
  258 tcp_tv_to_hptstick(struct timeval *sv)
  259 {
  260         return ((sv->tv_sec * 100000) + (sv->tv_usec / 10));
  261 }
  262 
  263 static __inline uint32_t
  264 tcp_gethptstick(struct timeval *sv)
  265 {
  266         struct timeval tv;
  267 
  268         if (sv == NULL)
  269                 sv = &tv;
  270         microuptime(sv);
  271         return (tcp_tv_to_hptstick(sv));
  272 }
  273 
  274 static __inline uint32_t
  275 tcp_tv_to_usectick(struct timeval *sv)
  276 {
  277         return ((uint32_t) ((sv->tv_sec * HPTS_USEC_IN_SEC) + sv->tv_usec));
  278 }
  279 
  280 static __inline uint32_t
  281 tcp_tv_to_mssectick(struct timeval *sv)
  282 {
  283         return ((uint32_t) ((sv->tv_sec * HPTS_MSEC_IN_SEC) + (sv->tv_usec/HPTS_USEC_IN_MSEC)));
  284 }
  285 
  286 static __inline void
  287 tcp_hpts_unlock(struct tcp_hpts_entry *hpts)
  288 {
  289         mtx_unlock(&hpts->p_mtx);
  290 }
  291 
  292 static __inline uint32_t
  293 tcp_get_usecs(struct timeval *tv)
  294 {
  295         struct timeval tvd;
  296 
  297         if (tv == NULL)
  298                 tv = &tvd;
  299         microuptime(tv);
  300         return (tcp_tv_to_usectick(tv));
  301 }
  302 
  303 #endif /* _KERNEL */
  304 #endif /* __tcp_hpts_h__ */

Cache object: 8a366a5cf604cfc6e2f23f842737e705


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.