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