| 735 | } |
| 736 | |
| 737 | Status AddTc(ServerContext*, const AddTcRequest* request, |
| 738 | EmptyResponse* response) override { |
| 739 | std::lock_guard<std::recursive_mutex> lock(mutex_); |
| 740 | |
| 741 | WorkerPauser wp; |
| 742 | |
| 743 | const char* tc_name = request->class_().name().c_str(); |
| 744 | if (request->class_().name().length() == 0) { |
| 745 | return return_with_error(response, EINVAL, "Missing 'name' field"); |
| 746 | } else if (tc_name[0] == '!') { |
| 747 | return return_with_error(response, EINVAL, |
| 748 | "TC names starting with \'!\' are reserved"); |
| 749 | } |
| 750 | |
| 751 | if (TrafficClassBuilder::all_tcs().count(tc_name)) { |
| 752 | return return_with_error(response, EINVAL, "Name '%s' already exists", |
| 753 | tc_name); |
| 754 | } |
| 755 | |
| 756 | const std::string& policy = request->class_().policy(); |
| 757 | |
| 758 | bess::TrafficClass* c = nullptr; |
| 759 | if (policy == bess::TrafficPolicyName[bess::POLICY_PRIORITY]) { |
| 760 | c = reinterpret_cast<bess::TrafficClass*>( |
| 761 | TrafficClassBuilder::CreateTrafficClass<bess::PriorityTrafficClass>( |
| 762 | tc_name)); |
| 763 | } else if (policy == bess::TrafficPolicyName[bess::POLICY_WEIGHTED_FAIR]) { |
| 764 | const std::string& resource = request->class_().resource(); |
| 765 | if (bess::ResourceMap.count(resource) == 0) { |
| 766 | return return_with_error(response, EINVAL, "Invalid resource"); |
| 767 | } |
| 768 | c = reinterpret_cast<bess::TrafficClass*>( |
| 769 | TrafficClassBuilder::CreateTrafficClass< |
| 770 | bess::WeightedFairTrafficClass>(tc_name, |
| 771 | bess::ResourceMap.at(resource))); |
| 772 | } else if (policy == bess::TrafficPolicyName[bess::POLICY_ROUND_ROBIN]) { |
| 773 | c = reinterpret_cast<bess::TrafficClass*>( |
| 774 | TrafficClassBuilder::CreateTrafficClass<bess::RoundRobinTrafficClass>( |
| 775 | tc_name)); |
| 776 | } else if (policy == bess::TrafficPolicyName[bess::POLICY_RATE_LIMIT]) { |
| 777 | uint64_t limit = 0; |
| 778 | uint64_t max_burst = 0; |
| 779 | const std::string& resource = request->class_().resource(); |
| 780 | const auto& limits = request->class_().limit(); |
| 781 | const auto& max_bursts = request->class_().max_burst(); |
| 782 | if (bess::ResourceMap.count(resource) == 0) { |
| 783 | return return_with_error(response, EINVAL, "Invalid resource"); |
| 784 | } |
| 785 | if (limits.find(resource) != limits.end()) { |
| 786 | limit = limits.at(resource); |
| 787 | } |
| 788 | if (max_bursts.find(resource) != max_bursts.end()) { |
| 789 | max_burst = max_bursts.at(resource); |
| 790 | } |
| 791 | c = reinterpret_cast<bess::TrafficClass*>( |
| 792 | TrafficClassBuilder::CreateTrafficClass<bess::RateLimitTrafficClass>( |
| 793 | tc_name, bess::ResourceMap.at(resource), limit, max_burst)); |
| 794 | } else if (policy == bess::TrafficPolicyName[bess::POLICY_LEAF]) { |