Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "bgp/l3vpn/inetvpn_address.h" 6 : 7 : #include <algorithm> 8 : 9 : #include "bgp/inet/inet_route.h" 10 : 11 : using std::copy; 12 : using std::string; 13 : 14 71834 : InetVpnPrefix::InetVpnPrefix() : prefixlen_(0) { 15 71834 : } 16 : 17 67271 : int InetVpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix, 18 : InetVpnPrefix *prefix, const BgpAttr *attr, 19 : uint32_t *label) { 20 67271 : size_t nlri_size = proto_prefix.prefix.size(); 21 67271 : size_t expected_min_nlri_size = 22 67271 : BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize; 23 : 24 67271 : if (nlri_size < expected_min_nlri_size) 25 1 : return -1; 26 67270 : if (nlri_size > expected_min_nlri_size + Address::kMaxV4Bytes) 27 1 : return -1; 28 : 29 67269 : bool is_vni = false; 30 67269 : if (attr != NULL) { 31 45742 : const ExtCommunity *extcomm = attr->ext_community(); 32 45742 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) { 33 19 : is_vni = true; 34 : } 35 : } 36 : 37 67269 : size_t label_offset = 0; 38 67269 : *label = proto_prefix.ReadLabel(label_offset, is_vni); //was ,false 39 67269 : size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize; 40 67269 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]); 41 : 42 67269 : size_t prefix_offset = rd_offset + RouteDistinguisher::kSize; 43 67269 : prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8; 44 67269 : Ip4Address::bytes_type bt = { { 0 } }; 45 67269 : copy(proto_prefix.prefix.begin() + prefix_offset, 46 : proto_prefix.prefix.end(), bt.begin()); 47 67269 : prefix->addr_ = Ip4Address(bt); 48 : 49 67269 : return 0; 50 : } 51 : 52 67266 : int InetVpnPrefix::FromProtoPrefix(BgpServer *server, 53 : const BgpProtoPrefix &proto_prefix, 54 : const BgpAttr *attr, 55 : const Address::Family family, 56 : InetVpnPrefix *prefix, 57 : BgpAttrPtr *new_attr, uint32_t *label, 58 : uint32_t *l3_label) { 59 67266 : int rval = FromProtoPrefix(proto_prefix, prefix, attr, label); 60 67266 : return rval; 61 : } 62 : 63 74113 : void InetVpnPrefix::BuildProtoPrefix(uint32_t label, 64 : BgpProtoPrefix *proto_prefix, const BgpAttr *attr) const { 65 74113 : proto_prefix->prefix.clear(); 66 74111 : size_t prefix_size = (prefixlen_ + 7) / 8; 67 74111 : size_t nlri_size = 68 74111 : BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize + prefix_size; 69 : 70 74111 : proto_prefix->prefix.resize(nlri_size, 0); 71 74103 : size_t label_offset = 0; 72 : 73 74103 : bool is_vni = false; 74 74103 : if (attr != NULL) { 75 45928 : const ExtCommunity *extcomm = attr->ext_community(); 76 45928 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) { 77 19 : is_vni = true; 78 : } 79 : } 80 : 81 74098 : proto_prefix->WriteLabel(label_offset, label, is_vni); // was false 82 74097 : size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize; 83 74098 : copy(rd_.GetData(), rd_.GetData() + RouteDistinguisher::kSize, 84 74097 : proto_prefix->prefix.begin() + rd_offset); 85 : 86 74096 : size_t prefix_offset = rd_offset + RouteDistinguisher::kSize; 87 74096 : proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_; 88 74096 : const Ip4Address::bytes_type &addr_bytes = addr_.to_bytes(); 89 74094 : copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size, 90 74096 : proto_prefix->prefix.begin() + prefix_offset); 91 74092 : } 92 : 93 : // RD:inet4-prefix 94 4561 : InetVpnPrefix InetVpnPrefix::FromString(const string &str, 95 : boost::system::error_code *errorp) { 96 4561 : InetVpnPrefix prefix; 97 : 98 4561 : size_t pos = str.rfind(':'); 99 4561 : if (pos == string::npos) { 100 3 : if (errorp != NULL) { 101 3 : *errorp = make_error_code(boost::system::errc::invalid_argument); 102 : } 103 3 : return prefix; 104 : } 105 4558 : string rdstr = str.substr(0, pos); 106 4558 : boost::system::error_code rderr; 107 4558 : prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr); 108 4558 : if (rderr.failed()) { 109 0 : if (errorp != NULL) { 110 0 : *errorp = rderr; 111 : } 112 0 : return prefix; 113 : } 114 : 115 4558 : string ip4pstr(str, pos + 1); 116 4558 : boost::system::error_code pfxerr = Ip4SubnetParse(ip4pstr, &prefix.addr_, 117 : &prefix.prefixlen_); 118 4558 : if (errorp != NULL) { 119 1763 : *errorp = pfxerr; 120 : } 121 4558 : return prefix; 122 4558 : } 123 : 124 69 : string InetVpnPrefix::ToString() const { 125 69 : Ip4Prefix prefix(addr_, prefixlen_); 126 138 : return (rd_.ToString() + ":" + prefix.ToString()); 127 : } 128 : 129 : // Check whether 'this' is more specific than rhs. 130 40 : bool InetVpnPrefix::IsMoreSpecific(const InetVpnPrefix &rhs) const { 131 40 : Ip4Prefix this_prefix(addr_, prefixlen_); 132 40 : Ip4Prefix match_prefix(rhs.addr(), rhs.prefixlen()); 133 : 134 80 : return this_prefix.IsMoreSpecific(match_prefix); 135 : } 136 : 137 9 : bool InetVpnPrefix::operator==(const InetVpnPrefix &rhs) const { 138 18 : return (rd_ == rhs.rd_ && 139 18 : addr_ == rhs.addr_ && 140 18 : prefixlen_ == rhs.prefixlen_); 141 : }