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