Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers trickle.c Source File

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 }