| 222 | |
| 223 | #ifdef ROUTE_MPATH |
| 224 | static void |
| 225 | decompose_change_notification(struct rib_cmd_info *rc, route_notification_t *cb, |
| 226 | void *cbdata) |
| 227 | { |
| 228 | uint32_t num_old, num_new; |
| 229 | uint32_t nh_idx_old, nh_idx_new; |
| 230 | struct weightened_nhop *wn_old, *wn_new; |
| 231 | struct weightened_nhop tmp = { NULL, 0 }; |
| 232 | uint32_t idx_old = 0, idx_new = 0; |
| 233 | |
| 234 | struct rib_cmd_info rc_del = { .rc_cmd = RTM_DELETE, .rc_rt = rc->rc_rt }; |
| 235 | struct rib_cmd_info rc_add = { .rc_cmd = RTM_ADD, .rc_rt = rc->rc_rt }; |
| 236 | |
| 237 | if (NH_IS_NHGRP(rc->rc_nh_old)) { |
| 238 | wn_old = nhgrp_get_nhops((struct nhgrp_object *)rc->rc_nh_old, &num_old); |
| 239 | } else { |
| 240 | tmp.nh = rc->rc_nh_old; |
| 241 | tmp.weight = rc->rc_nh_weight; |
| 242 | wn_old = &tmp; |
| 243 | num_old = 1; |
| 244 | } |
| 245 | if (NH_IS_NHGRP(rc->rc_nh_new)) { |
| 246 | wn_new = nhgrp_get_nhops((struct nhgrp_object *)rc->rc_nh_new, &num_new); |
| 247 | } else { |
| 248 | tmp.nh = rc->rc_nh_new; |
| 249 | tmp.weight = rc->rc_nh_weight; |
| 250 | wn_new = &tmp; |
| 251 | num_new = 1; |
| 252 | } |
| 253 | |
| 254 | /* Use the fact that each @wn array is sorted */ |
| 255 | /* |
| 256 | * Want to convert into set of add and delete operations |
| 257 | * [1] -> [1, 2] = A{2} |
| 258 | * [2] -> [1, 2] = A{1} |
| 259 | * [1, 2, 4]->[1, 3, 4] = A{2}, D{3} |
| 260 | * [1, 2, 4]->[1, 4] = D{2} |
| 261 | * [1, 2, 4] -> [3, 4] = D{1}, C{2,3} OR C{1,3}, D{2} OR D{1},D{2},A{3} |
| 262 | * [1, 2] -> [3, 4] = |
| 263 | * |
| 264 | */ |
| 265 | idx_old = 0; |
| 266 | while ((idx_old < num_old) && (idx_new < num_new)) { |
| 267 | nh_idx_old = wn_old[idx_old].nh->nh_priv->nh_idx; |
| 268 | nh_idx_new = wn_new[idx_new].nh->nh_priv->nh_idx; |
| 269 | |
| 270 | if (nh_idx_old == nh_idx_new) { |
| 271 | if (wn_old[idx_old].weight != wn_new[idx_new].weight) { |
| 272 | /* Update weight by providing del/add notifications */ |
| 273 | rc_del.rc_nh_old = wn_old[idx_old].nh; |
| 274 | rc_del.rc_nh_weight = wn_old[idx_old].weight; |
| 275 | cb(&rc_del, cbdata); |
| 276 | |
| 277 | rc_add.rc_nh_new = wn_new[idx_new].nh; |
| 278 | rc_add.rc_nh_weight = wn_new[idx_new].weight; |
| 279 | cb(&rc_add, cbdata); |
| 280 | } |
| 281 | idx_old++; |
no test coverage detected