Expose path change count to destination in mpath info
Unified · Split
| @@ -1439,7 +1439,8 @@ enum mpath_info_flags { · 1438 unmodified lines | ||
| 1439 | 1439 | MPATH_INFO_DISCOVERY_TIMEOUT = BIT(4), |
| 1440 | 1440 | MPATH_INFO_DISCOVERY_RETRIES = BIT(5), |
| 1441 | 1441 | MPATH_INFO_FLAGS = BIT(6), |
| 1442 | − MPATH_INFO_HOP_COUNT = BIT(7) | |
| 1442 | + MPATH_INFO_HOP_COUNT = BIT(7), | |
| 1443 | + MPATH_INFO_PATH_CHANGE = BIT(8), | |
| 1443 | 1444 | }; |
| 1444 | 1445 | |
| 1445 | 1446 | /** |
| @@ -1460,6 +1461,7 @@ enum mpath_info_flags { · 14 unmodified lines | ||
| 1460 | 1461 | * changes, i.e. when a station is added or removed, so that |
| 1461 | 1462 | * userspace can tell whether it got a consistent snapshot. |
| 1462 | 1463 | * @hop_count: hops to destination |
| 1464 | + * @path_change_count: total number of path changes to destination | |
| 1463 | 1465 | */ |
| 1464 | 1466 | struct mpath_info { |
| 1465 | 1467 | u32 filled; |
| @@ -1471,6 +1473,7 @@ struct mpath_info { · 5 unmodified lines | ||
| 1471 | 1473 | u8 discovery_retries; |
| 1472 | 1474 | u8 flags; |
| 1473 | 1475 | u8 hop_count; |
| 1476 | + u32 path_change_count; | |
| 1474 | 1477 | |
| 1475 | 1478 | int generation; |
| 1476 | 1479 | }; |
| @@ -3288,8 +3288,9 @@ enum nl80211_mpath_flags { · 3287 unmodified lines | ||
| 3288 | 3288 | * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec |
| 3289 | 3289 | * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries |
| 3290 | 3290 | * @NL80211_MPATH_INFO_HOP_COUNT: hop count to destination |
| 3291 | + * @NL80211_MPATH_INFO_PATH_CHANGE: total number of path changes to destination | |
| 3291 | 3292 | * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number |
| 3292 | − * currently defind | |
| 3293 | + * currently defined | |
| 3293 | 3294 | * @__NL80211_MPATH_INFO_AFTER_LAST: internal use |
| 3294 | 3295 | */ |
| 3295 | 3296 | enum nl80211_mpath_info { |
| @@ -3302,6 +3303,7 @@ enum nl80211_mpath_info { · 6 unmodified lines | ||
| 3302 | 3303 | NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, |
| 3303 | 3304 | NL80211_MPATH_INFO_DISCOVERY_RETRIES, |
| 3304 | 3305 | NL80211_MPATH_INFO_HOP_COUNT, |
| 3306 | + NL80211_MPATH_INFO_PATH_CHANGE, | |
| 3305 | 3307 | |
| 3306 | 3308 | /* keep last */ |
| 3307 | 3309 | __NL80211_MPATH_INFO_AFTER_LAST, |
| @@ -1746,7 +1746,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, · 1745 unmodified lines | ||
| 1746 | 1746 | MPATH_INFO_DISCOVERY_TIMEOUT | |
| 1747 | 1747 | MPATH_INFO_DISCOVERY_RETRIES | |
| 1748 | 1748 | MPATH_INFO_FLAGS | |
| 1749 | − MPATH_INFO_HOP_COUNT; | |
| 1749 | + MPATH_INFO_HOP_COUNT | | |
| 1750 | + MPATH_INFO_PATH_CHANGE; | |
| 1750 | 1751 | |
| 1751 | 1752 | pinfo->frame_qlen = mpath->frame_queue.qlen; |
| 1752 | 1753 | pinfo->sn = mpath->sn; |
| @@ -1767,6 +1768,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, · 14 unmodified lines | ||
| 1767 | 1768 | if (mpath->flags & MESH_PATH_RESOLVED) |
| 1768 | 1769 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED; |
| 1769 | 1770 | pinfo->hop_count = mpath->hop_count; |
| 1771 | + pinfo->path_change_count = mpath->path_change_count; | |
| 1770 | 1772 | } |
| 1771 | 1773 | |
| 1772 | 1774 | static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, |
| @@ -94,6 +94,7 @@ enum mesh_deferred_task_flags { · 93 unmodified lines | ||
| 94 | 94 | * @last_preq_to_root: Timestamp of last PREQ sent to root |
| 95 | 95 | * @is_root: the destination station of this path is a root node |
| 96 | 96 | * @is_gate: the destination station of this path is a mesh gate |
| 97 | + * @path_change_count: the number of path changes to destination | |
| 97 | 98 | * |
| 98 | 99 | * |
| 99 | 100 | * The dst address is unique in the mesh path table. Since the mesh_path is |
| @@ -124,6 +125,7 @@ struct mesh_path { · 24 unmodified lines | ||
| 124 | 125 | unsigned long last_preq_to_root; |
| 125 | 126 | bool is_root; |
| 126 | 127 | bool is_gate; |
| 128 | + u32 path_change_count; | |
| 127 | 129 | }; |
| 128 | 130 | |
| 129 | 131 | /** |
| @@ -479,6 +479,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, · 478 unmodified lines | ||
| 479 | 479 | } |
| 480 | 480 | |
| 481 | 481 | if (fresh_info) { |
| 482 | + if (rcu_access_pointer(mpath->next_hop) != sta) | |
| 483 | + mpath->path_change_count++; | |
| 482 | 484 | mesh_path_assign_nexthop(mpath, sta); |
| 483 | 485 | mpath->flags |= MESH_PATH_SN_VALID; |
| 484 | 486 | mpath->metric = new_metric; |
| @@ -523,6 +525,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, · 38 unmodified lines | ||
| 523 | 525 | } |
| 524 | 526 | |
| 525 | 527 | if (fresh_info) { |
| 528 | + if (rcu_access_pointer(mpath->next_hop) != sta) | |
| 529 | + mpath->path_change_count++; | |
| 526 | 530 | mesh_path_assign_nexthop(mpath, sta); |
| 527 | 531 | mpath->metric = last_hop_metric; |
| 528 | 532 | mpath->exp_time = time_after(mpath->exp_time, exp_time) |
| @@ -5830,7 +5830,10 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq, · 5829 unmodified lines | ||
| 5830 | 5830 | pinfo->discovery_retries)) || |
| 5831 | 5831 | ((pinfo->filled & MPATH_INFO_HOP_COUNT) && |
| 5832 | 5832 | nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT, |
| 5833 | − pinfo->hop_count))) | |
| 5833 | + pinfo->hop_count)) || | |
| 5834 | + ((pinfo->filled & MPATH_INFO_PATH_CHANGE) && | |
| 5835 | + nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE, | |
| 5836 | + pinfo->path_change_count))) | |
| 5834 | 5837 | goto nla_put_failure; |
| 5835 | 5838 | |
| 5836 | 5839 | nla_nest_end(msg, pinfoattr); |