OpenSDN source code
bgp_message_builder.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
6 
7 #include <vector>
8 
9 #include "bgp/bgp_log.h"
10 #include "bgp/bgp_ribout.h"
11 #include "bgp/bgp_route.h"
12 #include "bgp/bgp_server.h"
13 #include "net/bgp_af.h"
14 #include "extended-community/tag.h"
15 #include "large-community/tag.h"
16 
17 using std::unique_ptr;
18 
19 BgpMessage::BgpMessage() : table_(NULL), datalen_(0) {
20 }
21 
23 }
24 
25 bool BgpMessage::StartReach(const RibOut *ribout, const RibOutAttr *roattr,
26  const BgpRoute *route) {
27  BgpProto::Update update;
28  const BgpAttr *attr = roattr->attr();
29  Address::Family family = table_->family();
30 
31  BgpAttrOrigin *origin = new BgpAttrOrigin(attr->origin());
32  update.path_attributes.push_back(origin);
33 
34  if ((BgpAf::FamilyToAfi(family) == BgpAf::IPv4) &&
35  (BgpAf::FamilyToSafi(family) == BgpAf::Unicast)) {
36  BgpAttrNextHop *nh =
37  new BgpAttrNextHop(attr->nexthop().to_v4().to_ulong());
38  update.path_attributes.push_back(nh);
39  }
40 
41  if (attr->med()) {
42  BgpAttrMultiExitDisc *med = new BgpAttrMultiExitDisc(attr->med());
43  update.path_attributes.push_back(med);
44  }
45 
46  if (ribout->peer_type() == BgpProto::IBGP) {
47  BgpAttrLocalPref *lp = new BgpAttrLocalPref(attr->local_pref());
48  update.path_attributes.push_back(lp);
49  }
50 
51  if (attr->atomic_aggregate()) {
53  update.path_attributes.push_back(aa);
54  }
55 
56  if (attr->aggregator_as_num()) {
57  if (ribout->as4_supported()) {
59  attr->aggregator_as_num(),
60  attr->aggregator_adderess().to_v4().to_ulong());
61  update.path_attributes.push_back(agg);
62  } else {
63  if (attr->aggregator_as_num() > 0xffff) {
64  // For old neighbor, need to send AS4_Aggregator along with
65  // AS_TRANS in regular aggregator attribute
67  AS_TRANS, attr->aggregator_adderess().to_v4().to_ulong());
68  update.path_attributes.push_back(agg);
70  attr->aggregator_as_num(),
71  attr->aggregator_adderess().to_v4().to_ulong());
72  update.path_attributes.push_back(as4_agg);
73  } else {
75  attr->aggregator_as_num(),
76  attr->aggregator_adderess().to_v4().to_ulong());
77  update.path_attributes.push_back(agg);
78  }
79  }
80  }
81 
82  if (!attr->originator_id().is_unspecified()) {
83  BgpAttrOriginatorId *originator_id =
84  new BgpAttrOriginatorId(attr->originator_id().to_ulong());
85  update.path_attributes.push_back(originator_id);
86  }
87 
88  if (attr->cluster_list()) {
89  ClusterListSpec *clist =
91  update.path_attributes.push_back(clist);
92  }
93 
94 
95  if (ribout->as4_supported()) {
96  if (attr->aspath_4byte()) {
97  AsPath4ByteSpec *path = new AsPath4ByteSpec(
98  attr->aspath_4byte()->path());
99  update.path_attributes.push_back(path);
100  }
101  } else {
102  if (attr->as_path()) {
103  AsPathSpec *path = new AsPathSpec(attr->as_path()->path());
104  update.path_attributes.push_back(path);
105  }
106  if (attr->as4_path()) {
107  As4PathSpec *path = new As4PathSpec(attr->as4_path()->path());
108  update.path_attributes.push_back(path);
109  }
110  }
111 
112  if (attr->edge_discovery()) {
113  EdgeDiscoverySpec *edspec =
115  update.path_attributes.push_back(edspec);
116  }
117 
118  if (attr->edge_forwarding()) {
119  EdgeForwardingSpec *efspec =
121  update.path_attributes.push_back(efspec);
122  }
123 
124  if (attr->community() && attr->community()->communities().size()) {
125  CommunitySpec *comm = new CommunitySpec;
126  comm->communities = attr->community()->communities();
127  update.path_attributes.push_back(comm);
128  }
129 
130  ExtCommunitySpec *ext_comm = new ExtCommunitySpec;
131  if (attr->ext_community() && attr->ext_community()->communities().size()) {
133  attr->ext_community()->communities();
134  for (ExtCommunity::ExtCommunityList::const_iterator it = v.begin();
135  it != v.end(); ++it) {
136  uint64_t value = get_value(it->data(), it->size());
137  ext_comm->communities.push_back(value);
138  }
139  }
140 
141  LargeCommunitySpec *large_comm = new LargeCommunitySpec;
142  if (attr->large_community() && attr->large_community()->communities().size()) {
143  uint16_t tag_index = 0;
145  attr->large_community()->communities();
146  uint64_t tid64;
147  uint32_t asn, tid, value;
148  for (LargeCommunity::LargeCommunityList::const_iterator it = v.begin();
149  it != v.end(); ++it) {
150  TagLC tag_lc {*it};
151  tid64 = tag_lc.tag();
152  if ((tid64 & 0xFFFF0000) == 0) {
153  asn = tag_lc.as_number();
154  tid = ((tid64 & 0xFFFF00000000) >> 16) |
155  (tid64 & 0xFFFF);
156  if (asn <= AS2_MAX) {
157  Tag tag {as2_t(asn), tid};
158  ext_comm->communities.push_back(tag.GetExtCommunityValue());
159  } else {
160  Tag4ByteAs tag4 {asn, tag_index};
161  Tag tag {tag_index, tid};
162  ext_comm->communities.push_back(tag.GetExtCommunityValue());
163  ext_comm->communities.push_back(tag4.GetExtCommunityValue());
164  tag_index++;
165  }
166  continue;
167  }
168 
169  for (int i = 0; i < 3; i++) {
170  value = get_value(it->data() + 4*i, 4);
171  large_comm->communities.push_back(value);
172  }
173  }
174  update.path_attributes.push_back(large_comm);
175  }
176  if (ext_comm->EncodeLength()) {
177  update.path_attributes.push_back(ext_comm);
178  }
179 
180  if (attr->origin_vn_path() && attr->origin_vn_path()->origin_vns().size()) {
181  OriginVnPathSpec *ovnpath_spec = new OriginVnPathSpec;
182  const OriginVnPath::OriginVnList &v =
183  attr->origin_vn_path()->origin_vns();
184  for (OriginVnPath::OriginVnList::const_iterator it = v.begin();
185  it != v.end(); ++it) {
186  uint64_t value = get_value(it->data(), it->size());
187  ovnpath_spec->origin_vns.push_back(value);
188  }
189  update.path_attributes.push_back(ovnpath_spec);
190  }
191 
192  if (attr->pmsi_tunnel()) {
193  PmsiTunnelSpec *pmsi_spec =
194  new PmsiTunnelSpec(attr->pmsi_tunnel()->pmsi_tunnel());
195  update.path_attributes.push_back(pmsi_spec);
196  }
197 
198  std::vector<uint8_t> nh;
199 
200  route->BuildBgpProtoNextHop(nh, attr->nexthop());
201 
202  BgpMpNlri *nlri = new BgpMpNlri(
204  BgpAf::FamilyToSafi(family), nh);
205  update.path_attributes.push_back(nlri);
206 
207  BgpProtoPrefix *prefix = new BgpProtoPrefix;
208  const uint32_t label = (family == Address::INET) ? 0 : roattr->label();
209  route->BuildProtoPrefix(prefix, attr, label, roattr->l3_label());
210  nlri->nlri.push_back(prefix);
211 
212  int result = BgpProto::Encode(&update, data_, sizeof(data_),
213  &encode_offsets_, ribout->as4_supported());
214  if (result <= 0) {
215  BGP_LOG_WARNING_STR(BgpMessageSend, BGP_LOG_FLAG_ALL,
216  "Error encoding reach message for route " << route->ToString() <<
217  " in table " << (table_ ? table_->name() : "unknown"));
219  return false;
220  }
221 
223  datalen_ = result;
224  return true;
225 }
226 
227 bool BgpMessage::StartUnreach(const BgpRoute *route) {
228  BgpProto::Update update;
229  Address::Family family = table_->family();
230 
231  BgpMpNlri *nlri =
233  BgpAf::FamilyToAfi(family), BgpAf::FamilyToSafi(family));
234  update.path_attributes.push_back(nlri);
235 
236  BgpProtoPrefix *prefix = new BgpProtoPrefix;
237  route->BuildProtoPrefix(prefix);
238  nlri->nlri.push_back(prefix);
239 
240  int result =
241  BgpProto::Encode(&update, data_, sizeof(data_), &encode_offsets_);
242  if (result <= 0) {
243  BGP_LOG_WARNING_STR(BgpMessageSend, BGP_LOG_FLAG_ALL,
244  "Error encoding unreach message for route " << route->ToString() <<
245  " in table " << (table_ ? table_->name() : "unknown"));
247  return false;
248  }
249 
251  datalen_ = result;
252  return true;
253 }
254 
256  Message::Reset();
257  table_ = NULL;
259  datalen_ = 0;
260 }
261 
262 bool BgpMessage::Start(const RibOut *ribout, bool cache_repr,
263  const RibOutAttr *roattr, const BgpRoute *route) {
264  Reset();
265  table_ = ribout->table();
266 
267  if (roattr->IsReachable()) {
268  return StartReach(ribout, roattr, route);
269  } else {
270  return StartUnreach(route);
271  }
272 }
273 
274 bool BgpMessage::UpdateLength(const char *tag, int size, int delta) {
275  int offset = encode_offsets_.FindOffset(tag);
276  if (offset < 0) {
277  return false;
278  }
279  int value = get_value(&data_[offset], size);
280  value += delta;
281  put_value(&data_[offset], size, value);
282  return true;
283 }
284 
285 bool BgpMessage::AddRoute(const BgpRoute *route, const RibOutAttr *roattr) {
286  uint8_t *data = data_ + datalen_;
287  size_t size = sizeof(data_) - datalen_;
288  Address::Family family = table_->family();
289 
290  BgpMpNlri nlri;
291  nlri.afi = BgpAf::FamilyToAfi(family);
292  nlri.safi = BgpAf::FamilyToSafi(family);
293  BgpProtoPrefix *prefix = new BgpProtoPrefix;
294  if (roattr) {
295  const uint32_t label = (family == Address::INET) ? 0 : roattr->label();
296  route->BuildProtoPrefix(prefix, roattr->attr(), label);
297  } else {
298  route->BuildProtoPrefix(prefix);
299  }
300  nlri.nlri.push_back(prefix);
301 
302  int result = BgpProto::Encode(&nlri, data, size);
303  if (result <= 0) {
304  return false;
305  }
306 
307  datalen_ += result;
308  if (roattr->IsReachable()) {
310  } else {
312  }
313 
314  if (!UpdateLength("BgpMsgLength", 2, result)) {
315  assert(false);
316  return false;
317  }
318 
319  if (!UpdateLength("BgpPathAttribute", 2, result)) {
320  assert(false);
321  return false;
322  }
323 
324  if (!UpdateLength("MpReachUnreachNlri", 2, result)) {
325  assert(false);
326  return false;
327  }
328 
329  return true;
330 }
331 
333 }
334 
335 const uint8_t *BgpMessage::GetData(IPeerUpdate *peer, size_t *lenp,
336  const string **msg_str, string *temp) {
337  *lenp = datalen_;
338  return data_;
339 }
340 
342  return new BgpMessage;
343 }
344 
346 : MessageBuilder() {
347 }
#define AS_TRANS
Definition: bgp_common.h:23
#define AS2_MAX
Definition: bgp_common.h:24
uint16_t as2_t
Definition: bgp_common.h:22
#define BGP_LOG_FLAG_ALL
Definition: bgp_log.h:44
#define BGP_LOG_WARNING_STR(obj, flags, arg)
Definition: bgp_log.h:107
Family
Definition: address.h:24
@ INET
Definition: address.h:26
const As4PathSpec & path() const
Definition: bgp_aspath.h:443
const AsPath4ByteSpec & path() const
Definition: bgp_aspath.h:285
const AsPathSpec & path() const
Definition: bgp_aspath.h:127
@ Unicast
Definition: bgp_af.h:25
static Afi FamilyToAfi(Address::Family family)
Definition: bgp_af.cc:159
static Safi FamilyToSafi(Address::Family family)
Definition: bgp_af.cc:188
@ IPv4
Definition: bgp_af.h:19
uint32_t local_pref() const
Definition: bgp_attr.h:891
const LargeCommunity * large_community() const
Definition: bgp_attr.h:918
const AsPath * as_path() const
Definition: bgp_attr.h:901
const IpAddress & aggregator_adderess() const
Definition: bgp_attr.h:896
const EdgeForwarding * edge_forwarding() const
Definition: bgp_attr.h:926
const ClusterList * cluster_list() const
Definition: bgp_attr.h:909
const OriginVnPath * origin_vn_path() const
Definition: bgp_attr.h:921
uint32_t med() const
Definition: bgp_attr.h:890
const Community * community() const
Definition: bgp_attr.h:916
as_t aggregator_as_num() const
Definition: bgp_attr.h:893
const IpAddress & nexthop() const
Definition: bgp_attr.h:888
const EdgeDiscovery * edge_discovery() const
Definition: bgp_attr.h:923
const ExtCommunity * ext_community() const
Definition: bgp_attr.h:917
const AsPath4Byte * aspath_4byte() const
Definition: bgp_attr.h:904
const Ip4Address & originator_id() const
Definition: bgp_attr.h:897
BgpAttrOrigin::OriginType origin() const
Definition: bgp_attr.h:883
const PmsiTunnel * pmsi_tunnel() const
Definition: bgp_attr.h:922
const As4Path * as4_path() const
Definition: bgp_attr.h:913
bool atomic_aggregate() const
Definition: bgp_attr.h:892
virtual Message * Create() const
virtual ~BgpMessage()
virtual bool Start(const RibOut *ribout, bool cache_routes, const RibOutAttr *roattr, const BgpRoute *route)
uint8_t data_[BgpProto::kMaxMessageSize]
virtual void Reset()
virtual const uint8_t * GetData(IPeerUpdate *peer, size_t *lenp, const std::string **msg_str, std::string *temp)
bool StartReach(const RibOut *ribout, const RibOutAttr *roattr, const BgpRoute *route)
const BgpTable * table_
bool UpdateLength(const char *tag, int size, int delta)
virtual bool AddRoute(const BgpRoute *route, const RibOutAttr *roattr)
EncodeOffsets encode_offsets_
bool StartUnreach(const BgpRoute *route)
virtual void Finish()
static int Encode(const BgpMessage *msg, uint8_t *data, size_t size, EncodeOffsets *offsets=NULL, bool as4=false)
Definition: bgp_proto.cc:2135
virtual void BuildProtoPrefix(BgpProtoPrefix *prefix, const BgpAttr *attr=NULL, uint32_t label=0, uint32_t l3_label=0) const
Definition: bgp_route.h:67
virtual void BuildBgpProtoNextHop(std::vector< uint8_t > &nh, IpAddress nexthop) const
Definition: bgp_route.h:72
void increment_message_build_error() const
Definition: bgp_server.h:276
BgpServer * server()
Definition: bgp_table.cc:87
virtual Address::Family family() const =0
const ClusterListSpec & cluster_list() const
Definition: bgp_attr.h:229
const std::vector< uint32_t > & communities() const
Definition: community.h:67
virtual std::string ToString() const =0
const std::string & name() const
Definition: db_table.h:110
const EdgeDiscoverySpec & edge_discovery() const
Definition: bgp_attr.h:470
const EdgeForwardingSpec & edge_forwarding() const
Definition: bgp_attr.h:577
void ClearOffsets()
Definition: parse_object.h:97
std::vector< uint64_t > communities
Definition: community.h:145
virtual size_t EncodeLength() const
Definition: community.cc:266
std::vector< ExtCommunityValue > ExtCommunityList
Definition: community.h:155
const ExtCommunityList & communities() const
Definition: community.h:182
This class encapsulates the wire-format representation of a BGP Large Community attribute and provide...
Definition: community.h:508
std::vector< uint32_t > communities
Vector of community values. Each Large Community value consists of three 4-byte fields (12 bytes tota...
Definition: community.h:540
const LargeCommunityList & communities() const
Get the list of Large Community values.
Definition: community.h:594
std::vector< LargeCommunityValue > LargeCommunityList
A list (vector) of LargeCommunityValue items.
Definition: community.h:562
uint64_t num_reach_route_
virtual void Reset()
uint64_t num_unreach_route_
std::vector< OriginVnValue > OriginVnList
const OriginVnList & origin_vns() const
const PmsiTunnelSpec & pmsi_tunnel() const
Definition: bgp_attr.h:373
const BgpAttr * attr() const
Definition: bgp_ribout.h:98
bool IsReachable() const
Definition: bgp_ribout.h:95
uint32_t l3_label() const
Definition: bgp_ribout.h:119
uint32_t label() const
Definition: bgp_ribout.h:116
BgpProto::BgpPeerType peer_type() const
Definition: bgp_ribout.h:321
BgpTable * table()
Definition: bgp_ribout.h:305
bool as4_supported() const
Definition: bgp_ribout.h:326
Represents a single BGP Large Community tag.
uint64_t tag() const
Returns the tag id.
static void put_value(uint8_t *data, int size, uint64_t value)
Definition: parse_object.h:55
static uint64_t get_value(const uint8_t *data, int size)
Definition: parse_object.h:39
uint8_t safi
Definition: bgp_attr.h:308
uint16_t afi
Definition: bgp_attr.h:307
std::vector< BgpProtoPrefix * > nlri
Definition: bgp_attr.h:311
std::vector< BgpAttribute * > path_attributes
Definition: bgp_proto.h:435
std::vector< uint32_t > communities
Definition: community.h:35
std::vector< uint64_t > origin_vns