Line data Source code
1 : /* 2 : * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "bgp/routing-policy/routing_policy_action.h" 6 : 7 : #include <boost/foreach.hpp> 8 : 9 : #include <algorithm> 10 : #include <sstream> 11 : 12 : #include "bgp/bgp_attr.h" 13 : #include "bgp/bgp_server.h" 14 : #include "bgp/community.h" 15 : 16 : using std::copy; 17 : using std::ostringstream; 18 : using std::string; 19 : using std::vector; 20 : 21 13 : UpdateAsPath::UpdateAsPath(const vector<uint32_t> &asn_list) 22 13 : : asn_list_(asn_list) { 23 13 : } 24 : 25 6 : void UpdateAsPath::operator()(BgpAttr *attr) const { 26 6 : if (!attr) 27 0 : return; 28 6 : BgpAttrDB *attr_db = attr->attr_db(); 29 6 : BgpServer *server = attr_db->server(); 30 6 : if (!server->enable_4byte_as()) { 31 3 : const AsPath *as_path = attr->as_path(); 32 3 : if (as_path) { 33 1 : const AsPathSpec &as_path_spec = as_path->path(); 34 1 : AsPathSpec *as_path_spec_ptr = as_path_spec.Add(asn_list_); 35 1 : attr->set_as_path(as_path_spec_ptr); 36 1 : delete as_path_spec_ptr; 37 : } else { 38 2 : AsPathSpec as_path_spec; 39 2 : AsPathSpec *as_path_spec_ptr = as_path_spec.Add(asn_list_); 40 2 : attr->set_as_path(as_path_spec_ptr); 41 2 : delete as_path_spec_ptr; 42 2 : } 43 : } else { 44 3 : const AsPath4Byte *as_path = attr->aspath_4byte(); 45 3 : if (as_path) { 46 1 : const AsPath4ByteSpec &as_path_spec = as_path->path(); 47 1 : AsPath4ByteSpec *as_path_spec_ptr = as_path_spec.Add(asn_list_); 48 1 : attr->set_aspath_4byte(as_path_spec_ptr); 49 1 : delete as_path_spec_ptr; 50 : } else { 51 2 : AsPath4ByteSpec as_path_spec; 52 2 : AsPath4ByteSpec *as_path_spec_ptr = as_path_spec.Add(asn_list_); 53 2 : attr->set_aspath_4byte(as_path_spec_ptr); 54 2 : delete as_path_spec_ptr; 55 2 : } 56 : } 57 : } 58 : 59 1 : string UpdateAsPath::ToString() const { 60 1 : ostringstream oss; 61 1 : oss << "as-path expand [ "; 62 5 : BOOST_FOREACH(uint32_t asn, asn_list_) { 63 2 : oss << asn << ","; 64 : } 65 1 : oss.seekp(-1, oss.cur); 66 1 : oss << " ]"; 67 2 : return oss.str(); 68 1 : } 69 : 70 6 : bool UpdateAsPath::IsEqual(const RoutingPolicyAction &as_path) const { 71 6 : const UpdateAsPath in_as_path = static_cast<const UpdateAsPath&>(as_path); 72 12 : return (asn_list_ == in_as_path.asn_list_); 73 6 : } 74 : 75 124 : UpdateCommunity::UpdateCommunity(const std::vector<string> communities, 76 124 : string op) { 77 476 : BOOST_FOREACH(const string &community, communities) { 78 176 : uint32_t value = CommunityType::CommunityFromString(community); 79 176 : if (value) communities_.push_back(value); 80 : } 81 124 : std::sort(communities_.begin(), communities_.end()); 82 : std::vector<uint32_t>::iterator it = 83 124 : std::unique(communities_.begin(), communities_.end()); 84 124 : communities_.erase(it, communities_.end()); 85 : 86 124 : if (strcmp(op.c_str(), "add") == 0) { 87 76 : op_ = ADD; 88 48 : } else if (strcmp(op.c_str(), "remove") == 0) { 89 24 : op_ = REMOVE; 90 24 : } else if (strcmp(op.c_str(), "set") == 0) { 91 24 : op_ = SET; 92 : } 93 124 : } 94 : 95 44 : void UpdateCommunity::operator()(BgpAttr *attr) const { 96 44 : if (!attr) return; 97 44 : const Community *comm = attr->community(); 98 44 : BgpAttrDB *attr_db = attr->attr_db(); 99 44 : BgpServer *server = attr_db->server(); 100 44 : CommunityDB *comm_db = server->comm_db(); 101 44 : CommunityPtr new_community = NULL; 102 44 : if (op_ == SET) { 103 7 : new_community = comm_db->SetAndLocate(comm, communities_); 104 37 : } else if (op_ == ADD) { 105 31 : new_community = comm_db->AppendAndLocate(comm, communities_); 106 6 : } else if (op_ == REMOVE) { 107 6 : if (comm) new_community = comm_db->RemoveAndLocate(comm, communities_); 108 : } 109 44 : attr->set_community(new_community); 110 44 : } 111 : 112 8 : string UpdateCommunity::ToString() const { 113 8 : ostringstream oss; 114 8 : if (op_ == SET) oss << "community set [ "; 115 6 : else if (op_ == ADD) oss << "community add [ "; 116 4 : else if (op_ == REMOVE) oss << "community remove [ "; 117 : 118 24 : BOOST_FOREACH(uint32_t community, communities()) { 119 8 : string name = CommunityType::CommunityToString(community); 120 8 : oss << name << ","; 121 8 : } 122 8 : oss.seekp(-1, oss.cur); 123 8 : oss << " ]"; 124 16 : return oss.str(); 125 8 : } 126 : 127 63 : bool UpdateCommunity::IsEqual(const RoutingPolicyAction &community) const { 128 : const UpdateCommunity in_comm = 129 63 : static_cast<const UpdateCommunity&>(community); 130 63 : if (op_ == in_comm.op_) 131 63 : return (communities() == in_comm.communities()); 132 0 : return false; 133 63 : } 134 : 135 40 : UpdateExtCommunity::UpdateExtCommunity(const std::vector<string> &communities, 136 40 : string op) { 137 182 : BOOST_FOREACH(const string &community, communities) { 138 : const ExtCommunity::ExtCommunityList list = 139 71 : ExtCommunity::ExtCommunityFromString(community); 140 71 : if (list.size()) 141 67 : communities_.push_back(list[0]); 142 71 : } 143 40 : std::sort(communities_.begin(), communities_.end()); 144 : ExtCommunity::ExtCommunityList::iterator it = 145 40 : std::unique(communities_.begin(), communities_.end()); 146 40 : communities_.erase(it, communities_.end()); 147 : 148 40 : if (strcmp(op.c_str(), "add") == 0) { 149 24 : op_ = ADD; 150 16 : } else if (strcmp(op.c_str(), "remove") == 0) { 151 11 : op_ = REMOVE; 152 5 : } else if (strcmp(op.c_str(), "set") == 0) { 153 5 : op_ = SET; 154 : } 155 40 : } 156 : 157 24 : void UpdateExtCommunity::operator()(BgpAttr *attr) const { 158 24 : if (!attr) return; 159 24 : const ExtCommunity *comm = attr->ext_community(); 160 24 : BgpAttrDB *attr_db = attr->attr_db(); 161 24 : BgpServer *server = attr_db->server(); 162 24 : ExtCommunityDB *comm_db = server->extcomm_db(); 163 24 : ExtCommunityPtr new_community = NULL; 164 24 : if (op_ == SET) { 165 3 : new_community = comm_db->SetAndLocate(comm, communities_); 166 21 : } else if (op_ == ADD) { 167 15 : new_community = comm_db->AppendAndLocate(comm, communities_); 168 6 : } else if (op_ == REMOVE) { 169 6 : new_community = comm_db->RemoveAndLocate(comm, communities_); 170 : } 171 24 : attr->set_ext_community(new_community); 172 24 : } 173 : 174 7 : string UpdateExtCommunity::ToString() const { 175 7 : ostringstream oss; 176 7 : if (op_ == SET) oss << "Extcommunity set [ "; 177 7 : else if (op_ == ADD) oss << "Extcommunity add [ "; 178 0 : else if (op_ == REMOVE) oss << "Extcommunity remove [ "; 179 : 180 23 : BOOST_FOREACH(ExtCommunity::ExtCommunityValue community, communities()) { 181 8 : string name = ExtCommunity::ToString(community); 182 8 : oss << name << ","; 183 8 : } 184 7 : oss.seekp(-1, oss.cur); 185 7 : oss << " ]"; 186 14 : return oss.str(); 187 7 : } 188 : 189 15 : bool UpdateExtCommunity::IsEqual(const RoutingPolicyAction &community) const { 190 : const UpdateExtCommunity in_comm = 191 15 : static_cast<const UpdateExtCommunity&>(community); 192 15 : if (op_ == in_comm.op_) 193 15 : return (communities() == in_comm.communities()); 194 0 : return false; 195 15 : } 196 : 197 180 : UpdateLocalPref::UpdateLocalPref(uint32_t local_pref) 198 180 : : local_pref_(local_pref) { 199 180 : } 200 : 201 120 : void UpdateLocalPref::operator()(BgpAttr *attr) const { 202 120 : attr->set_local_pref(local_pref_); 203 120 : } 204 : 205 12 : string UpdateLocalPref::ToString() const { 206 12 : ostringstream oss; 207 12 : oss << "local-pref " << local_pref_; 208 24 : return oss.str(); 209 12 : } 210 : 211 96 : bool UpdateLocalPref::IsEqual(const RoutingPolicyAction &local_pref) const { 212 : const UpdateLocalPref in_lp = 213 96 : static_cast<const UpdateLocalPref&>(local_pref); 214 192 : return (local_pref_ == in_lp.local_pref_); 215 96 : } 216 : 217 2 : UpdateMed::UpdateMed(uint32_t med) 218 2 : : med_(med) { 219 2 : } 220 : 221 1 : void UpdateMed::operator()(BgpAttr *attr) const { 222 1 : attr->set_med(med_); 223 1 : } 224 : 225 0 : string UpdateMed::ToString() const { 226 0 : ostringstream oss; 227 0 : oss << "med " << med_; 228 0 : return oss.str(); 229 0 : } 230 : 231 1 : bool UpdateMed::IsEqual(const RoutingPolicyAction &med) const { 232 : const UpdateMed in_med = 233 1 : static_cast<const UpdateMed&>(med); 234 2 : return (med_ == in_med.med_); 235 1 : }