Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 12:45:34 by
