Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers multicast_api.c Source File

multicast_api.c

00001 /*
00002  * Copyright (c) 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 #include "nsconfig.h"
00019 #include <string.h>
00020 #include "NWK_INTERFACE/Include/protocol.h"
00021 #include "Common_Protocols/ipv6_constants.h"
00022 #include "MPL/mpl.h"
00023 #include "multicast_api.h"
00024 
00025 #ifdef MULTICAST_FORWARDING
00026 int8_t multicast_fwd_add(int8_t interface_id, const uint8_t group[16], uint32_t lifetime)
00027 {
00028     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00029     if (!cur) {
00030         return -1;
00031     }
00032     return addr_multicast_fwd_add(cur, group, lifetime) ? 0 : -1;
00033 }
00034 
00035 int8_t multicast_fwd_remove(int8_t interface_id, const uint8_t group[16])
00036 {
00037     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00038     if (!cur) {
00039         return -1;
00040     }
00041     return addr_multicast_fwd_remove(cur, group) ? 0 : -1;
00042 }
00043 
00044 int8_t multicast_fwd_full_for_scope(int8_t interface_id, uint_fast8_t min_scope)
00045 {
00046     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00047     if (!cur) {
00048         return -1;
00049     }
00050     cur->ip_mcast_fwd_for_scope = min_scope;
00051     return 0;
00052 }
00053 
00054 int8_t multicast_fwd_set_forwarding(int8_t interface_id, bool enable)
00055 {
00056     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00057     if (!cur) {
00058         return -1;
00059     }
00060     addr_multicast_fwd_set_forwarding(cur, enable);
00061     return 0;
00062 }
00063 
00064 int8_t multicast_fwd_set_proxy_upstream(int8_t interface_id)
00065 {
00066     protocol_interface_info_entry_t *upstream;
00067     if (interface_id < 0) {
00068         upstream = NULL;
00069     } else {
00070         upstream = protocol_stack_interface_info_get_by_id(interface_id);
00071         if (!upstream || !upstream->ip_multicast_forwarding) {
00072             return -1;
00073         }
00074     }
00075 
00076     protocol_interface_info_entry_t *old_upstream = protocol_core_multicast_upstream;
00077     protocol_core_multicast_upstream = upstream;
00078 
00079     if (upstream != old_upstream) {
00080         /* Try to maintain correct state */
00081         addr_multicast_fwd_adjust_upstream_full(old_upstream, false);
00082         addr_multicast_fwd_adjust_upstream_full(upstream, true);
00083     }
00084     return 0;
00085 }
00086 
00087 #else // MULTICAST_FORWARDING
00088 
00089 int8_t multicast_fwd_add(int8_t interface_id, const uint8_t group[16], uint32_t lifetime)
00090 {
00091     (void) interface_id;
00092     (void) group;
00093     (void) lifetime;
00094     return -1;
00095 }
00096 
00097 int8_t multicast_fwd_remove(int8_t interface_id, const uint8_t group[16])
00098 {
00099     (void) interface_id;
00100     (void) group;
00101     return -1;
00102 }
00103 
00104 int8_t multicast_fwd_full_for_scope(int8_t interface_id, uint_fast8_t min_scope)
00105 {
00106     (void) interface_id;
00107     (void) min_scope;
00108     return -1;
00109 }
00110 
00111 int8_t multicast_fwd_set_forwarding(int8_t interface_id, bool enable)
00112 {
00113     (void) interface_id;
00114     (void) enable;
00115     return -1;
00116 }
00117 
00118 int8_t multicast_fwd_set_proxy_upstream(int8_t interface_id)
00119 {
00120     (void) interface_id;
00121     return -1;
00122 }
00123 #endif // MULTICAST_FORWARDING
00124 
00125 #ifdef HAVE_MPL
00126 
00127 int8_t multicast_mpl_domain_subscribe(int8_t interface_id,
00128                                       const uint8_t address[16],
00129                                       multicast_mpl_seed_id_mode_e seed_id_mode,
00130                                       const void *seed_id)
00131 {
00132     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
00133     if (!interface) {
00134         return -1;
00135     }
00136 
00137     return mpl_domain_create(interface, address, seed_id, seed_id_mode, -1, 0, NULL, NULL) ? 0 : -1;
00138 }
00139 
00140 int8_t multicast_mpl_domain_subscribe_with_parameters
00141                                      (int8_t interface_id,
00142                                       const uint8_t address[16],
00143                                       multicast_mpl_seed_id_mode_e seed_id_mode,
00144                                       const void *seed_id,
00145                                       bool proactive_forwarding,
00146                                       uint16_t seed_set_entry_lifetime,
00147                                       uint32_t data_message_imin,
00148                                       uint32_t data_message_imax,
00149                                       uint8_t data_message_k,
00150                                       uint8_t data_message_timer_expirations,
00151                                       uint32_t control_message_imin,
00152                                       uint32_t control_message_imax,
00153                                       uint8_t control_message_k,
00154                                       uint8_t control_message_timer_expirations)
00155 {
00156     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
00157     if (!interface) {
00158         return -1;
00159     }
00160 
00161     const trickle_params_t data_params = {
00162         .Imax = MPL_MS_TO_TICKS(data_message_imax),
00163         .Imin = MPL_MS_TO_TICKS(data_message_imin),
00164         .k = data_message_k,
00165         .TimerExpirations = data_message_timer_expirations
00166     },
00167     control_params = {
00168         .Imax = MPL_MS_TO_TICKS(control_message_imax),
00169         .Imin = MPL_MS_TO_TICKS(control_message_imin),
00170         .k = control_message_k,
00171         .TimerExpirations = control_message_timer_expirations
00172     };
00173     return mpl_domain_create(interface, address, seed_id, seed_id_mode, proactive_forwarding, seed_set_entry_lifetime, &data_params, &control_params) ? 0 : -1;
00174 }
00175 
00176 int_fast8_t multicast_mpl_set_default_parameters(int8_t interface_id,
00177                                                  bool proactive_forwarding,
00178                                                  uint16_t seed_set_entry_lifetime,
00179                                                  uint32_t data_message_imin,
00180                                                  uint32_t data_message_imax,
00181                                                  uint8_t data_message_k,
00182                                                  uint8_t data_message_timer_expirations,
00183                                                  uint32_t control_message_imin,
00184                                                  uint32_t control_message_imax,
00185                                                  uint8_t control_message_k,
00186                                                  uint8_t control_message_timer_expirations)
00187 {
00188     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get(interface_id);
00189     if (!interface) {
00190         return -1;
00191     }
00192 
00193     interface->mpl_proactive_forwarding = proactive_forwarding;
00194     interface->mpl_seed_set_entry_lifetime = seed_set_entry_lifetime;
00195     interface->mpl_data_trickle_params.Imin = MPL_MS_TO_TICKS(data_message_imin);
00196     interface->mpl_data_trickle_params.Imax = MPL_MS_TO_TICKS(data_message_imax);
00197     interface->mpl_data_trickle_params.k = data_message_k;
00198     interface->mpl_data_trickle_params.TimerExpirations = data_message_timer_expirations;
00199     interface->mpl_control_trickle_params.Imin = MPL_MS_TO_TICKS(control_message_imin);
00200     interface->mpl_control_trickle_params.Imax = MPL_MS_TO_TICKS(control_message_imax);
00201     interface->mpl_control_trickle_params.k = control_message_k;
00202     interface->mpl_control_trickle_params.TimerExpirations = control_message_timer_expirations;
00203 
00204     return 0;
00205 }
00206 
00207 int_fast8_t multicast_mpl_set_default_seed_id(int8_t interface_id,
00208                                               multicast_mpl_seed_id_mode_e seed_id_mode,
00209                                               const void *seed_id)
00210 {
00211     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
00212     if (!interface) {
00213         return -1;
00214     }
00215 
00216     switch (seed_id_mode) {
00217         case MULTICAST_MPL_SEED_ID_128_BIT:
00218         case MULTICAST_MPL_SEED_ID_64_BIT:
00219         case MULTICAST_MPL_SEED_ID_16_BIT:
00220             memcpy(interface->mpl_seed_id, seed_id, seed_id_mode);
00221             break;
00222         case MULTICAST_MPL_SEED_ID_IPV6_SRC_FOR_DOMAIN:
00223         case MULTICAST_MPL_SEED_ID_IID_EUI64:
00224         case MULTICAST_MPL_SEED_ID_IID_SLAAC:
00225         case MULTICAST_MPL_SEED_ID_MAC:
00226         case MULTICAST_MPL_SEED_ID_MAC_SHORT:
00227             break;
00228         default:
00229             return -2;
00230     }
00231 
00232     interface->mpl_seed_id_mode = seed_id_mode;
00233 
00234     return 0;
00235 }
00236 
00237 int8_t multicast_mpl_domain_unsubscribe(int8_t interface_id,
00238                                         const uint8_t address[16])
00239 {
00240     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
00241     if (!interface) {
00242         return -1;
00243     }
00244 
00245     return mpl_domain_delete(interface, address) ? 0 : -1;
00246 }
00247 
00248 void multicast_set_parameters(uint8_t i_min, uint8_t i_doublings, uint8_t k, uint8_t timer_expirations, uint16_t window_expiration)
00249 {
00250     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get(IF_6LoWPAN);
00251     if (!cur) {
00252         return;
00253     }
00254 
00255     trickle_time_t i_max = i_min;
00256     for (; i_doublings; i_doublings--) {
00257         if (i_max <= TRICKLE_TIME_MAX / 2) {
00258             i_max *= 2;
00259         } else {
00260             i_max = TRICKLE_TIME_MAX;
00261             break;
00262         }
00263     }
00264 
00265     /* Set the interface's default parameters, and also update the All-Forwarders domain */
00266     cur->mpl_data_trickle_params.Imin = i_min;
00267     cur->mpl_data_trickle_params.Imax = i_max;
00268     cur->mpl_data_trickle_params.k = k;
00269     cur->mpl_data_trickle_params.TimerExpirations = timer_expirations;
00270     /* MPL core uses a 4:1 ratio for seed and message lifetimes - we somewhat
00271      * arbitrarily treat window expiration parameter as a request for message lifetime.
00272      */
00273     uint32_t message_lifetime_ticks = (uint32_t) i_max * timer_expirations + window_expiration;
00274     uint32_t seed_lifetime_ticks = 4 * message_lifetime_ticks;
00275     cur->mpl_seed_set_entry_lifetime = (seed_lifetime_ticks + 20) / 20; // convert to seconds
00276     mpl_domain_t *domain = mpl_domain_lookup(cur, ADDR_ALL_MPL_FORWARDERS);
00277     if (!domain) {
00278         return;
00279     }
00280 
00281     mpl_domain_change_timing(domain, &cur->mpl_data_trickle_params, cur->mpl_seed_set_entry_lifetime);
00282 }
00283 
00284 #else // HAVE_MPL
00285 
00286 int8_t multicast_mpl_domain_subscribe(int8_t interface_id,
00287                                       const uint8_t address[16],
00288                                       multicast_mpl_seed_id_mode_e seed_id_mode,
00289                                       const void *seed_id)
00290 {
00291     (void) interface_id;
00292     (void) address;
00293     (void) seed_id_mode;
00294     (void) seed_id;
00295     return -1;
00296 }
00297 
00298 int8_t multicast_mpl_domain_subscribe_with_parameters
00299                                      (int8_t interface_id,
00300                                       const uint8_t address[16],
00301                                       multicast_mpl_seed_id_mode_e seed_id_mode,
00302                                       const void *seed_id,
00303                                       bool proactive_forwarding,
00304                                       uint16_t seed_set_entry_lifetime,
00305                                       uint32_t data_message_imin,
00306                                       uint32_t data_message_imax,
00307                                       uint8_t data_message_k,
00308                                       uint8_t data_message_timer_expirations,
00309                                       uint32_t control_message_imin,
00310                                       uint32_t control_message_imax,
00311                                       uint8_t control_message_k,
00312                                       uint8_t control_message_timer_expirations)
00313 {
00314     (void) interface_id;
00315     (void) address;
00316     (void) seed_id_mode;
00317     (void) seed_id;
00318     (void) proactive_forwarding;
00319     (void) seed_set_entry_lifetime;
00320     (void) data_message_imin;
00321     (void) data_message_imax;
00322     (void) data_message_k;
00323     (void) data_message_timer_expirations;
00324     (void) control_message_imin;
00325     (void) control_message_imax;
00326     (void) control_message_k;
00327     (void) control_message_timer_expirations;
00328     return -1;
00329 }
00330 
00331 int_fast8_t multicast_mpl_set_default_parameters(int8_t interface_id,
00332                                                  bool proactive_forwarding,
00333                                                  uint16_t seed_set_entry_lifetime,
00334                                                  uint32_t data_message_imin,
00335                                                  uint32_t data_message_imax,
00336                                                  uint8_t data_message_k,
00337                                                  uint8_t data_message_timer_expirations,
00338                                                  uint32_t control_message_imin,
00339                                                  uint32_t control_message_imax,
00340                                                  uint8_t control_message_k,
00341                                                  uint8_t control_message_timer_expirations)
00342 {
00343     (void) interface_id;
00344     (void) proactive_forwarding;
00345     (void) seed_set_entry_lifetime;
00346     (void) data_message_imin;
00347     (void) data_message_imax;
00348     (void) data_message_k;
00349     (void) data_message_timer_expirations;
00350     (void) control_message_imin;
00351     (void) control_message_imax;
00352     (void) control_message_k;
00353     (void) control_message_timer_expirations;
00354     return -1;
00355 }
00356 
00357 int_fast8_t multicast_mpl_set_default_seed_id(int8_t interface_id,
00358                                               multicast_mpl_seed_id_mode_e seed_id_mode,
00359                                               const void *seed_id)
00360 {
00361     (void) interface_id;
00362     (void) seed_id_mode;
00363     (void) seed_id;
00364     return -1;
00365 }
00366 
00367 int8_t multicast_mpl_domain_unsubscribe(int8_t interface_id,
00368                                         const uint8_t address[16])
00369 {
00370     (void) interface_id;
00371     (void) address;
00372     return -1;
00373 }
00374 
00375 void multicast_set_parameters(uint8_t i_min, uint8_t i_doublings, uint8_t k, uint8_t timer_expirations, uint16_t window_expiration)
00376 {
00377     (void) i_min;
00378     (void) i_doublings;
00379     (void) k;
00380     (void) timer_expirations;
00381     (void) window_expiration;
00382 }
00383 
00384 #endif // HAVE_MPL
00385 
00386 uint8_t multicast_add_address(const uint8_t *address_ptr, uint8_t use_trickle MAYBE_UNUSED)
00387 {
00388     uint8_t ret_val = 1;
00389     if (!addr_is_ipv6_multicast(address_ptr)) {
00390         return 0;
00391     }
00392 
00393     uint8_t scope = addr_ipv6_multicast_scope(address_ptr);
00394     if (scope == 0) { // reserved
00395         return 0;
00396     } else if (scope <= IPV6_SCOPE_LINK_LOCAL) {
00397         use_trickle = false;
00398     }
00399 
00400     // Hacky hack.
00401     // Consider 6LoWPAN and Ethernet interfaces - if in the same scope zone, attach to one,
00402     // 6LoWPAN by preference. If different, attach to both.
00403     // If use_trickle is set, then
00404     //    1) Make sure MPL is enabled on 6LoWPAN by creating the ff03::fc domain
00405     //    2) Subscribe to that MPL domain if Realm Local and not acting as single domain
00406     //       (If larger scope, then we don't create a domain, we tunnel in ff03::fc)
00407     protocol_interface_info_entry_t *lowpan = protocol_stack_interface_info_get(IF_6LoWPAN);
00408     protocol_interface_info_entry_t *ethernet = protocol_stack_interface_info_get(IF_IPV6);
00409 
00410     if (lowpan && ethernet &&
00411             lowpan->zone_index[scope] == ethernet->zone_index[scope]) {
00412         ethernet = NULL; // Both interfaces in same zone, join only on 6LoWPAN
00413     }
00414 
00415     if (lowpan) {
00416 #ifdef HAVE_MPL
00417         if (use_trickle && !lowpan->mpl_seed) {
00418             mpl_domain_create(lowpan, ADDR_ALL_MPL_FORWARDERS, NULL, MULTICAST_MPL_SEED_ID_DEFAULT, -1, 0, NULL, NULL);
00419         }
00420 
00421         if (use_trickle && scope == IPV6_SCOPE_REALM_LOCAL && !lowpan->mpl_treat_realm_domains_as_one) {
00422             ret_val = multicast_mpl_domain_subscribe(lowpan->id, address_ptr, MULTICAST_MPL_SEED_ID_DEFAULT, NULL);
00423         } else
00424 #endif
00425         {
00426             addr_add_group(lowpan, address_ptr);
00427         }
00428     }
00429 
00430     if (ethernet) {
00431         addr_add_group(ethernet, address_ptr);
00432     }
00433 
00434     return ret_val;
00435 }
00436 
00437 uint8_t multicast_free_address(const uint8_t *address_ptr)
00438 {
00439     // Hacky hack
00440     protocol_interface_info_entry_t *lowpan = protocol_stack_interface_info_get(IF_6LoWPAN);
00441     if (lowpan) {
00442 #ifdef HAVE_MPL
00443         /* First try to delete from MPL - if that fails, delete as plain group */
00444         if (multicast_mpl_domain_unsubscribe(lowpan->id, address_ptr) < 0)
00445 #endif
00446         {
00447             addr_remove_group(lowpan, address_ptr);
00448         }
00449     }
00450 
00451     protocol_interface_info_entry_t *ethernet = protocol_stack_interface_info_get(IF_IPV6);
00452     if (ethernet) {
00453         addr_remove_group(ethernet, address_ptr);
00454     }
00455     return 0;
00456 }