|
20 | 20 | #include <vector> |
21 | 21 |
|
22 | 22 | #include "absl/status/statusor.h" |
| 23 | +#include "absl/strings/ascii.h" |
| 24 | +#include "absl/strings/numbers.h" |
23 | 25 | #include "absl/strings/str_replace.h" |
24 | 26 | #include "absl/strings/str_split.h" |
| 27 | +#include "gutil/proto.h" |
25 | 28 | #include "gutil/status.h" |
| 29 | +#include "p4/config/v1/p4types.pb.h" |
26 | 30 |
|
27 | 31 | namespace pdpi { |
28 | 32 | namespace { |
@@ -175,4 +179,142 @@ absl::StatusOr<std::vector<std::string>> ParseAsArgList(std::string value) { |
175 | 179 | } |
176 | 180 |
|
177 | 181 | } // namespace annotation |
| 182 | + |
| 183 | +absl::StatusOr<std::vector<WcmpGroupMode>> ParseRequiredModesFromActionProfile( |
| 184 | + const p4::config::v1::ActionProfile& action_profile) { |
| 185 | + std::vector<WcmpGroupMode> modes; |
| 186 | + |
| 187 | + auto clean_token = [](absl::string_view s) -> std::string { |
| 188 | + s = absl::StripAsciiWhitespace(s); |
| 189 | + if (s.size() >= 2 && s.front() == '"' && s.back() == '"') { |
| 190 | + s = s.substr(1, s.size() - 2); |
| 191 | + s = absl::StripAsciiWhitespace(s); |
| 192 | + } |
| 193 | + return std::string(s); |
| 194 | + }; |
| 195 | + |
| 196 | + auto parse_kv_pairs = [&](const p4::config::v1::KeyValuePairList& kv_list) { |
| 197 | + WcmpGroupMode mode; |
| 198 | + for (const auto& kv : kv_list.kv_pairs()) { |
| 199 | + if (kv.key() == "action_selection_mode") { |
| 200 | + std::string val = clean_token(kv.value().string_value()); |
| 201 | + if (val == "HASH" || val == "hash") { |
| 202 | + mode.set_action_selection_mode(WcmpGroupMode::HASH); |
| 203 | + } else if (val == "RANDOM" || val == "random") { |
| 204 | + mode.set_action_selection_mode(WcmpGroupMode::RANDOM); |
| 205 | + } else if (val == "DEFAULT_MODE_DETERMINED_BY_ACTION_SELECTOR" || |
| 206 | + val == "default_mode_determined_by_action_selector") { |
| 207 | + mode.set_action_selection_mode( |
| 208 | + WcmpGroupMode::DEFAULT_MODE_DETERMINED_BY_ACTION_SELECTOR); |
| 209 | + } |
| 210 | + } else if (kv.key() == "size_semantics") { |
| 211 | + std::string val = clean_token(kv.value().string_value()); |
| 212 | + if (val == "sum_of_weights" || val == "SUM_OF_WEIGHTS") { |
| 213 | + mode.set_size_semantics(WcmpGroupMode::SUM_OF_WEIGHTS); |
| 214 | + } else if (val == "sum_of_members" || val == "SUM_OF_MEMBERS") { |
| 215 | + mode.set_size_semantics(WcmpGroupMode::SUM_OF_MEMBERS); |
| 216 | + } else if (val == "DEFAULT_SIZE_DETERMINED_BY_ACTION_SELECTOR" || |
| 217 | + val == "default_size_determined_by_action_selector") { |
| 218 | + mode.set_size_semantics( |
| 219 | + WcmpGroupMode::DEFAULT_SIZE_DETERMINED_BY_ACTION_SELECTOR); |
| 220 | + } |
| 221 | + } else if (kv.key() == "member_multiplier") { |
| 222 | + if (kv.value().has_int64_value()) { |
| 223 | + mode.set_member_multiplier(kv.value().int64_value()); |
| 224 | + } |
| 225 | + } else if (kv.key() == "max_member_weight") { |
| 226 | + if (kv.value().has_int64_value()) { |
| 227 | + mode.set_max_member_weight(kv.value().int64_value()); |
| 228 | + } |
| 229 | + } |
| 230 | + } |
| 231 | + modes.push_back(mode); |
| 232 | + }; |
| 233 | + |
| 234 | + auto parse_mode_args = [&](const std::vector<std::string>& args) { |
| 235 | + if (args.size() < 3) return; |
| 236 | + WcmpGroupMode mode; |
| 237 | + |
| 238 | + std::string action_selection_mode = clean_token(args[0]); |
| 239 | + if (action_selection_mode == "HASH" || action_selection_mode == "hash") { |
| 240 | + mode.set_action_selection_mode(WcmpGroupMode::HASH); |
| 241 | + } else if (action_selection_mode == "RANDOM" || |
| 242 | + action_selection_mode == "random") { |
| 243 | + mode.set_action_selection_mode(WcmpGroupMode::RANDOM); |
| 244 | + } else if (action_selection_mode == |
| 245 | + "DEFAULT_MODE_DETERMINED_BY_ACTION_SELECTOR" || |
| 246 | + action_selection_mode == |
| 247 | + "default_mode_determined_by_action_selector") { |
| 248 | + mode.set_action_selection_mode( |
| 249 | + WcmpGroupMode::DEFAULT_MODE_DETERMINED_BY_ACTION_SELECTOR); |
| 250 | + } |
| 251 | + |
| 252 | + std::vector<std::string> size_semantics_parts = |
| 253 | + absl::StrSplit(clean_token(args[1]), absl::MaxSplits(':', 1)); |
| 254 | + if (!size_semantics_parts.empty()) { |
| 255 | + std::string size_semantics = clean_token(size_semantics_parts[0]); |
| 256 | + if (size_semantics == "sum_of_weights" || |
| 257 | + size_semantics == "SUM_OF_WEIGHTS") { |
| 258 | + mode.set_size_semantics(WcmpGroupMode::SUM_OF_WEIGHTS); |
| 259 | + } else if (size_semantics == "sum_of_members" || |
| 260 | + size_semantics == "SUM_OF_MEMBERS") { |
| 261 | + mode.set_size_semantics(WcmpGroupMode::SUM_OF_MEMBERS); |
| 262 | + } else if (size_semantics == |
| 263 | + "DEFAULT_SIZE_DETERMINED_BY_ACTION_SELECTOR" || |
| 264 | + size_semantics == |
| 265 | + "default_size_determined_by_action_selector") { |
| 266 | + mode.set_size_semantics( |
| 267 | + WcmpGroupMode::DEFAULT_SIZE_DETERMINED_BY_ACTION_SELECTOR); |
| 268 | + } |
| 269 | + if (size_semantics_parts.size() > 1 && |
| 270 | + mode.size_semantics() == WcmpGroupMode::SUM_OF_MEMBERS) { |
| 271 | + int64_t val; |
| 272 | + if (absl::SimpleAtoi(clean_token(size_semantics_parts[1]), &val)) { |
| 273 | + mode.set_member_multiplier(val); |
| 274 | + } |
| 275 | + } |
| 276 | + } |
| 277 | + |
| 278 | + int64_t val; |
| 279 | + if (absl::SimpleAtoi(clean_token(args[2]), &val)) { |
| 280 | + if (mode.size_semantics() == WcmpGroupMode::SUM_OF_MEMBERS) { |
| 281 | + mode.set_max_member_weight(val); |
| 282 | + } else if (mode.size_semantics() == WcmpGroupMode::SUM_OF_WEIGHTS) { |
| 283 | + mode.set_member_multiplier(val); |
| 284 | + } |
| 285 | + } |
| 286 | + |
| 287 | + modes.push_back(mode); |
| 288 | + }; |
| 289 | + |
| 290 | + for (const auto& sa : action_profile.preamble().structured_annotations()) { |
| 291 | + if (sa.name() != "required_modes") continue; |
| 292 | + if (sa.has_kv_pair_list()) { |
| 293 | + parse_kv_pairs(sa.kv_pair_list()); |
| 294 | + } else if (sa.has_expression_list()) { |
| 295 | + std::vector<std::string> args; |
| 296 | + for (const auto& expr : sa.expression_list().expressions()) { |
| 297 | + args.push_back(expr.string_value()); |
| 298 | + } |
| 299 | + parse_mode_args(args); |
| 300 | + } |
| 301 | + } |
| 302 | + |
| 303 | + std::vector<WcmpGroupMode> deduplicated_modes; |
| 304 | + for (const auto& mode : modes) { |
| 305 | + bool exists = false; |
| 306 | + for (const auto& existing : deduplicated_modes) { |
| 307 | + if (google::protobuf::util::MessageDifferencer::Equals(mode, existing)) { |
| 308 | + exists = true; |
| 309 | + break; |
| 310 | + } |
| 311 | + } |
| 312 | + if (!exists) { |
| 313 | + deduplicated_modes.push_back(mode); |
| 314 | + } |
| 315 | + } |
| 316 | + |
| 317 | + return deduplicated_modes; |
| 318 | +} |
| 319 | + |
178 | 320 | } // namespace pdpi |
0 commit comments