1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License as published by 4 * the Free Software Foundation; either version 2 of the License. 5 * 6 * This program is distributed in the hope that it will be useful, 7 * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 * GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License 12 * along with this program; if not, write to the Free Software 13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 14 * 15 * Copyright (C) 2020 embedd.ch 16 * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> 17 * Copyright (C) 2020 John Crispin <john@phrozen.org> 18 */ 19 20 #include "node.h" 21 #include "usteer.h" 22 23 struct usteer_remote_node *usteer_remote_node_by_bssid(uint8_t *bssid) { 24 struct usteer_remote_node *rn; 25 26 for_each_remote_node(rn) { 27 if (!memcmp(rn->node.bssid, bssid, 6)) 28 return rn; 29 } 30 31 return NULL; 32 } 33 34 struct usteer_node *usteer_node_by_bssid(uint8_t *bssid) { 35 struct usteer_remote_node *rn; 36 struct usteer_local_node *ln; 37 38 rn = usteer_remote_node_by_bssid(bssid); 39 if (rn) 40 return &rn->node; 41 42 ln = usteer_local_node_by_bssid(bssid); 43 if (ln) 44 return &ln->node; 45 46 return NULL; 47 } 48 49 void usteer_node_set_blob(struct blob_attr **dest, struct blob_attr *val) 50 { 51 int new_len; 52 int len; 53 54 if (!val) { 55 free(*dest); 56 *dest = NULL; 57 return; 58 } 59 60 len = *dest ? blob_pad_len(*dest) : 0; 61 new_len = blob_pad_len(val); 62 if (new_len != len) 63 *dest = realloc(*dest, new_len); 64 memcpy(*dest, val, new_len); 65 } 66 67 static struct usteer_node * 68 usteer_node_higher_bssid(struct usteer_node *node1, struct usteer_node *node2) 69 { 70 int i; 71 72 for (i = 0; i < 6; i++) { 73 if (node1->bssid[i] == node2->bssid[i]) 74 continue; 75 if (node1->bssid[i] < node2->bssid[i]) 76 return node2; 77 78 break; 79 } 80 81 return node1; 82 } 83 84 static struct usteer_node * 85 usteer_node_higher_roamability(struct usteer_node *node, struct usteer_node *ref) 86 { 87 uint64_t roamability_node, roamability_ref; 88 89 roamability_node = ((uint64_t)(node->roam_events.source + node->roam_events.target)) * current_time / ((current_time - node->created) + 1); 90 roamability_ref = ((uint64_t)(ref->roam_events.source + ref->roam_events.target)) * current_time / ((current_time - ref->created) + 1); 91 92 if (roamability_node < roamability_ref) 93 return ref; 94 95 return node; 96 } 97 98 static struct usteer_node * 99 usteer_node_better_neighbor(struct usteer_node *node, struct usteer_node *ref) 100 { 101 struct usteer_node *n1, *n2; 102 103 /** 104 * 1. Return one node if the other one is NULL 105 * 2. Return the node with the higher roam events. 106 * 3. Return the node with the higher BSSID. 107 * 4. Return first method argument. 108 */ 109 110 if (!ref) 111 return node; 112 113 if (!node) 114 return ref; 115 116 n1 = usteer_node_higher_roamability(node, ref); 117 n2 = usteer_node_higher_roamability(ref, node); 118 if (n1 == n2) 119 return n1; 120 121 /* Identical roam interactions. Check BSSID */ 122 n1 = usteer_node_higher_bssid(node, ref); 123 n2 = usteer_node_higher_bssid(ref, node); 124 if (n1 == n2) 125 return n1; 126 127 return node; 128 } 129 130 struct usteer_node * 131 usteer_node_get_next_neighbor(struct usteer_node *current_node, struct usteer_node *last) 132 { 133 struct usteer_remote_node *rn; 134 struct usteer_node *next = NULL, *n1, *n2; 135 136 for_each_remote_node(rn) { 137 if (next == &rn->node) 138 continue; 139 140 if (strcmp(current_node->ssid, rn->node.ssid)) 141 continue; 142 143 /* Skip nodes which can't handle additional STA */ 144 if (rn->node.max_assoc && rn->node.n_assoc >= rn->node.max_assoc) 145 continue; 146 147 /* Check if this node is ranked lower than the last one */ 148 n1 = usteer_node_better_neighbor(last, &rn->node); 149 n2 = usteer_node_better_neighbor(&rn->node, last); 150 if (n1 != n2) { 151 /* Identical rank. Skip. */ 152 continue; 153 } else if (last && n1 == &rn->node) { 154 /* Candidate rank is higher than the last neighbor. Skip. */ 155 continue; 156 } 157 158 /* Check with current next candidate */ 159 n1 = usteer_node_better_neighbor(next, &rn->node); 160 n2 = usteer_node_better_neighbor(&rn->node, next); 161 if (n1 != n2) { 162 /* Identical rank. Skip. */ 163 continue; 164 } else if (n1 != &rn->node) { 165 /* Next candidate ranked higher. */ 166 continue; 167 } 168 169 next = n1; 170 } 171 172 return next; 173 } 174
This page was automatically generated by LXR 0.3.1. • OpenWrt