BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
trickle.c
00001 /* 00002 * Copyright (c) 2014-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 /* 00018 * trickle.c 00019 * 00020 * Implement a generic RFC 6206 Trickle Algorithm 00021 */ 00022 #include "nsconfig.h" 00023 #include <ns_types.h> 00024 #include <randLIB.h> 00025 00026 #include "ns_trace.h" 00027 00028 #include "Service_Libs/Trickle/trickle.h" 00029 00030 #define TRACE_GROUP "tric" 00031 00032 /* RFC 6206 Rule 2 */ 00033 void trickle_begin_interval(trickle_t *t) 00034 { 00035 t->c = 0; 00036 if (t->I > 2) { //Take random only when t->I is bigger than 2 otherwise result will be 1 00037 t->t = randLIB_get_random_in_range(t->I / 2, t->I - 1); 00038 } else { 00039 t->t= 1; 00040 } 00041 t->now = 0; 00042 } 00043 00044 /* RFC 6206 Rule 1 */ 00045 void trickle_start(trickle_t *t, const trickle_params_t *params) 00046 { 00047 t->e = 0; 00048 t->I = randLIB_get_random_in_range(params->Imin, params->Imax); 00049 trickle_begin_interval(t); 00050 } 00051 00052 /* We don't expose the raw reset as API; users should use "inconsistent_heard". 00053 * This avoids repeated resets stopping transmission by restarting the interval. 00054 */ 00055 static void trickle_reset_timer(trickle_t *t, const trickle_params_t *params) 00056 { 00057 t->e = 0; 00058 t->I = params->Imin; 00059 trickle_begin_interval(t); 00060 00061 tr_debug("trickle reset timer"); 00062 } 00063 00064 /* RFC 6206 Rule 3 */ 00065 void trickle_consistent_heard(trickle_t *t) 00066 { 00067 if (t->c < UINT8_MAX) { 00068 t->c++; 00069 } 00070 } 00071 00072 /* RFC 6206 Rule 6 */ 00073 void trickle_inconsistent_heard(trickle_t *t, const trickle_params_t *params) 00074 { 00075 if (t->I != params->Imin || !trickle_running(t, params)) { 00076 trickle_reset_timer(t, params); 00077 } 00078 } 00079 00080 bool trickle_running(const trickle_t *t, const trickle_params_t *params) 00081 { 00082 return t->e < params->TimerExpirations; 00083 } 00084 00085 00086 /* Returns true if you should transmit now */ 00087 bool trickle_timer(trickle_t *t, const trickle_params_t *params, uint16_t ticks) 00088 { 00089 if (!trickle_running(t, params)) { 00090 return false; 00091 } 00092 00093 bool transmit = false; 00094 trickle_time_t new_time = t->now + ticks; 00095 00096 /* Catch overflow */ 00097 if (new_time < t->now) { 00098 new_time = TRICKLE_TIME_MAX; 00099 } 00100 00101 /* RFC 6206 Rule 4 */ 00102 if (t->now < t->t && new_time >= t->t) { 00103 /* Treat k == 0 as "infinity", as per RFC 6206 6.5 */ 00104 if (t->c < params->k || params->k == 0) { 00105 transmit = true; 00106 } 00107 } 00108 00109 /* RFC 6206 Rule 5 */ 00110 t->now = new_time; 00111 if (new_time >= t->I) { 00112 if (t->I <= TRICKLE_TIME_MAX / 2) { 00113 t->I *= 2; 00114 } else { 00115 t->I = TRICKLE_TIME_MAX; 00116 } 00117 00118 if (t->I > params->Imax) { 00119 t->I = params->Imax; 00120 } 00121 00122 if (t->e < UINT8_MAX) { 00123 t->e++; 00124 } 00125 trickle_begin_interval(t); 00126 } 00127 00128 return transmit; 00129 } 00130 00131 /* Stop the timer (by setting e to infinite) */ 00132 void trickle_stop(trickle_t *t) 00133 { 00134 t->e = TRICKLE_EXPIRATIONS_INFINITE; 00135 }
Generated on Tue Jul 12 2022 12:22:26 by
