michael@0: /* michael@0: * rdbx.h michael@0: * michael@0: * replay database with extended packet indices, using a rollover counter michael@0: * michael@0: * David A. McGrew michael@0: * Cisco Systems, Inc. michael@0: * michael@0: */ michael@0: /* michael@0: * michael@0: * Copyright (c) 2001-2006, Cisco Systems, Inc. michael@0: * All rights reserved. michael@0: * michael@0: * Redistribution and use in source and binary forms, with or without michael@0: * modification, are permitted provided that the following conditions michael@0: * are met: michael@0: * michael@0: * Redistributions of source code must retain the above copyright michael@0: * notice, this list of conditions and the following disclaimer. michael@0: * michael@0: * Redistributions in binary form must reproduce the above michael@0: * copyright notice, this list of conditions and the following michael@0: * disclaimer in the documentation and/or other materials provided michael@0: * with the distribution. michael@0: * michael@0: * Neither the name of the Cisco Systems, Inc. nor the names of its michael@0: * contributors may be used to endorse or promote products derived michael@0: * from this software without specific prior written permission. michael@0: * michael@0: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS michael@0: * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE michael@0: * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, michael@0: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES michael@0: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR michael@0: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) michael@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, michael@0: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) michael@0: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED michael@0: * OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: * michael@0: */ michael@0: michael@0: #ifndef RDBX_H michael@0: #define RDBX_H michael@0: michael@0: #include "datatypes.h" michael@0: #include "err.h" michael@0: michael@0: /* #define ROC_TEST */ michael@0: michael@0: #ifndef ROC_TEST michael@0: michael@0: typedef uint16_t sequence_number_t; /* 16 bit sequence number */ michael@0: typedef uint32_t rollover_counter_t; /* 32 bit rollover counter */ michael@0: michael@0: #else /* use small seq_num and roc datatypes for testing purposes */ michael@0: michael@0: typedef unsigned char sequence_number_t; /* 8 bit sequence number */ michael@0: typedef uint16_t rollover_counter_t; /* 16 bit rollover counter */ michael@0: michael@0: #endif michael@0: michael@0: #define seq_num_median (1 << (8*sizeof(sequence_number_t) - 1)) michael@0: #define seq_num_max (1 << (8*sizeof(sequence_number_t))) michael@0: michael@0: /* michael@0: * An xtd_seq_num_t is a 64-bit unsigned integer used as an 'extended' michael@0: * sequence number. michael@0: */ michael@0: michael@0: typedef uint64_t xtd_seq_num_t; michael@0: michael@0: michael@0: /* michael@0: * An rdbx_t is a replay database with extended range; it uses an michael@0: * xtd_seq_num_t and a bitmask of recently received indices. michael@0: */ michael@0: michael@0: typedef struct { michael@0: xtd_seq_num_t index; michael@0: bitvector_t bitmask; michael@0: } rdbx_t; michael@0: michael@0: michael@0: /* michael@0: * rdbx_init(rdbx_ptr, ws) michael@0: * michael@0: * initializes the rdbx pointed to by its argument with the window size ws, michael@0: * setting the rollover counter and sequence number to zero michael@0: */ michael@0: michael@0: err_status_t michael@0: rdbx_init(rdbx_t *rdbx, unsigned long ws); michael@0: michael@0: michael@0: /* michael@0: * rdbx_dealloc(rdbx_ptr) michael@0: * michael@0: * frees memory associated with the rdbx michael@0: */ michael@0: michael@0: err_status_t michael@0: rdbx_dealloc(rdbx_t *rdbx); michael@0: michael@0: michael@0: /* michael@0: * rdbx_estimate_index(rdbx, guess, s) michael@0: * michael@0: * given an rdbx and a sequence number s (from a newly arrived packet), michael@0: * sets the contents of *guess to contain the best guess of the packet michael@0: * index to which s corresponds, and returns the difference between michael@0: * *guess and the locally stored synch info michael@0: */ michael@0: michael@0: int michael@0: rdbx_estimate_index(const rdbx_t *rdbx, michael@0: xtd_seq_num_t *guess, michael@0: sequence_number_t s); michael@0: michael@0: /* michael@0: * rdbx_check(rdbx, delta); michael@0: * michael@0: * rdbx_check(&r, delta) checks to see if the xtd_seq_num_t michael@0: * which is at rdbx->window_start + delta is in the rdb michael@0: * michael@0: */ michael@0: michael@0: err_status_t michael@0: rdbx_check(const rdbx_t *rdbx, int difference); michael@0: michael@0: /* michael@0: * replay_add_index(rdbx, delta) michael@0: * michael@0: * adds the xtd_seq_num_t at rdbx->window_start + delta to replay_db michael@0: * (and does *not* check if that xtd_seq_num_t appears in db) michael@0: * michael@0: * this function should be called *only* after replay_check has michael@0: * indicated that the index does not appear in the rdbx, and a mutex michael@0: * should protect the rdbx between these calls if necessary. michael@0: */ michael@0: michael@0: err_status_t michael@0: rdbx_add_index(rdbx_t *rdbx, int delta); michael@0: michael@0: michael@0: /* michael@0: * rdbx_set_roc(rdbx, roc) initalizes the rdbx_t at the location rdbx michael@0: * to have the rollover counter value roc. If that value is less than michael@0: * the current rollover counter value, then the function returns michael@0: * err_status_replay_old; otherwise, err_status_ok is returned. michael@0: * michael@0: */ michael@0: michael@0: err_status_t michael@0: rdbx_set_roc(rdbx_t *rdbx, uint32_t roc); michael@0: michael@0: /* michael@0: * rdbx_get_roc(rdbx) returns the value of the rollover counter for michael@0: * the rdbx_t pointed to by rdbx michael@0: * michael@0: */ michael@0: michael@0: xtd_seq_num_t michael@0: rdbx_get_packet_index(const rdbx_t *rdbx); michael@0: michael@0: /* michael@0: * xtd_seq_num_t functions - these are *internal* functions of rdbx, and michael@0: * shouldn't be used to manipulate rdbx internal values. use the rdbx michael@0: * api instead! michael@0: */ michael@0: michael@0: /* michael@0: * rdbx_get_ws(rdbx_ptr) michael@0: * michael@0: * gets the window size which was used to initialize the rdbx michael@0: */ michael@0: michael@0: unsigned long michael@0: rdbx_get_window_size(const rdbx_t *rdbx); michael@0: michael@0: michael@0: /* index_init(&pi) initializes a packet index pi (sets it to zero) */ michael@0: michael@0: void michael@0: index_init(xtd_seq_num_t *pi); michael@0: michael@0: /* index_advance(&pi, s) advances a xtd_seq_num_t forward by s */ michael@0: michael@0: void michael@0: index_advance(xtd_seq_num_t *pi, sequence_number_t s); michael@0: michael@0: michael@0: /* michael@0: * index_guess(local, guess, s) michael@0: * michael@0: * given a xtd_seq_num_t local (which represents the highest michael@0: * known-to-be-good index) and a sequence number s (from a newly michael@0: * arrived packet), sets the contents of *guess to contain the best michael@0: * guess of the packet index to which s corresponds, and returns the michael@0: * difference between *guess and *local michael@0: */ michael@0: michael@0: int michael@0: index_guess(const xtd_seq_num_t *local, michael@0: xtd_seq_num_t *guess, michael@0: sequence_number_t s); michael@0: michael@0: michael@0: #endif /* RDBX_H */ michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: