OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 
15 using std::unique_ptr;
16 
17 BgpMessage::BgpMessage() : table_(NULL), datalen_(0) {
18 }
19 
21 }
22 
23 bool BgpMessage::StartReach(const RibOut *ribout, const RibOutAttr *roattr,
24  const BgpRoute *route) {
25  BgpProto::Update update;
26  const BgpAttr *attr = roattr->attr();
27  Address::Family family = table_->family();
28 
29  BgpAttrOrigin *origin = new BgpAttrOrigin(attr->origin());
30  update.path_attributes.push_back(origin);
31 
32  if ((BgpAf::FamilyToAfi(family) == BgpAf::IPv4) &&
33  (BgpAf::FamilyToSafi(family) == BgpAf::Unicast)) {
34  BgpAttrNextHop *nh =
35  new BgpAttrNextHop(attr->nexthop().to_v4().to_ulong());
36  update.path_attributes.push_back(nh);
37  }
38 
39  if (attr->med()) {
40  BgpAttrMultiExitDisc *med = new BgpAttrMultiExitDisc(attr->med());
41  update.path_attributes.push_back(med);
42  }
43 
44  if (ribout->peer_type() == BgpProto::IBGP) {
45  BgpAttrLocalPref *lp = new BgpAttrLocalPref(attr->local_pref());
46  update.path_attributes.push_back(lp);
47  }
48 
49  if (attr->atomic_aggregate()) {
51  update.path_attributes.push_back(aa);
52  }
53 
54  if (attr->aggregator_as_num()) {
55  if (ribout->as4_supported()) {
57  attr->aggregator_as_num(),
58  attr->aggregator_adderess().to_v4().to_ulong());
59  update.path_attributes.push_back(agg);
60  } else {
61  if (attr->aggregator_as_num() > 0xffff) {
62  // For old neighbor, need to send AS4_Aggregator along with
63  // AS_TRANS in regular aggregator attribute
65  AS_TRANS, attr->aggregator_adderess().to_v4().to_ulong());
66  update.path_attributes.push_back(agg);
68  attr->aggregator_as_num(),
69  attr->aggregator_adderess().to_v4().to_ulong());
70  update.path_attributes.push_back(as4_agg);
71  } else {
73  attr->aggregator_as_num(),
74  attr->aggregator_adderess().to_v4().to_ulong());
75  update.path_attributes.push_back(agg);
76  }
77  }
78  }
79 
80  if (!attr->originator_id().is_unspecified()) {
81  BgpAttrOriginatorId *originator_id =
82  new BgpAttrOriginatorId(attr->originator_id().to_ulong());
83  update.path_attributes.push_back(originator_id);
84  }
85 
86  if (attr->cluster_list()) {
87  ClusterListSpec *clist =
89  update.path_attributes.push_back(clist);
90  }
91 
92 
93  if (ribout->as4_supported()) {
94  if (attr->aspath_4byte()) {
95  AsPath4ByteSpec *path = new AsPath4ByteSpec(
96  attr->aspath_4byte()->path());
97  update.path_attributes.push_back(path);
98  }
99  } else {
100  if (attr->as_path()) {
101  AsPathSpec *path = new AsPathSpec(attr->as_path()->path());
102  update.path_attributes.push_back(path);
103  }
104  if (attr->as4_path()) {
105  As4PathSpec *path = new As4PathSpec(attr->as4_path()->path());
106  update.path_attributes.push_back(path);
107  }
108  }
109 
110  if (attr->edge_discovery()) {
111  EdgeDiscoverySpec *edspec =
113  update.path_attributes.push_back(edspec);
114  }
115 
116  if (attr->edge_forwarding()) {
117  EdgeForwardingSpec *efspec =
119  update.path_attributes.push_back(efspec);
120  }
121 
122  if (attr->community() && attr->community()->communities().size()) {
123  CommunitySpec *comm = new CommunitySpec;
124  comm->communities = attr->community()->communities();
125  update.path_attributes.push_back(comm);
126  }
127 
128  if (attr->ext_community() && attr->ext_community()->communities().size()) {
129  ExtCommunitySpec *ext_comm = new ExtCommunitySpec;
131  attr->ext_community()->communities();
132  for (ExtCommunity::ExtCommunityList::const_iterator it = v.begin();
133  it != v.end(); ++it) {
134  uint64_t value = get_value(it->data(), it->size());
135  ext_comm->communities.push_back(value);
136  }
137  update.path_attributes.push_back(ext_comm);
138  }
139 
140  if (attr->origin_vn_path() && attr->origin_vn_path()->origin_vns().size()) {
141  OriginVnPathSpec *ovnpath_spec = new OriginVnPathSpec;
142  const OriginVnPath::OriginVnList &v =
143  attr->origin_vn_path()->origin_vns();
144  for (OriginVnPath::OriginVnList::const_iterator it = v.begin();
145  it != v.end(); ++it) {
146  uint64_t value = get_value(it->data(), it->size());
147  ovnpath_spec->origin_vns.push_back(value);
148  }
149  update.path_attributes.push_back(ovnpath_spec);
150  }
151 
152  if (attr->pmsi_tunnel()) {
153  PmsiTunnelSpec *pmsi_spec =
154  new PmsiTunnelSpec(attr->pmsi_tunnel()->pmsi_tunnel());
155  update.path_attributes.push_back(pmsi_spec);
156  }
157 
158  std::vector<uint8_t> nh;
159 
160  route->BuildBgpProtoNextHop(nh, attr->nexthop());
161 
162  BgpMpNlri *nlri = new BgpMpNlri(
164  BgpAf::FamilyToSafi(family), nh);
165  update.path_attributes.push_back(nlri);
166 
167  BgpProtoPrefix *prefix = new BgpProtoPrefix;
168  const uint32_t label = (family == Address::INET) ? 0 : roattr->label();
169  route->BuildProtoPrefix(prefix, attr, label, roattr->l3_label());
170  nlri->nlri.push_back(prefix);
171 
172  int result = BgpProto::Encode(&update, data_, sizeof(data_),
173  &encode_offsets_, ribout->as4_supported());
174  if (result <= 0) {
175  BGP_LOG_WARNING_STR(BgpMessageSend, BGP_LOG_FLAG_ALL,
176  "Error encoding reach message for route " << route->ToString() <<
177  " in table " << (table_ ? table_->name() : "unknown"));
179  return false;
180  }
181 
183  datalen_ = result;
184  return true;
185 }
186 
187 bool BgpMessage::StartUnreach(const BgpRoute *route) {
188  BgpProto::Update update;
189  Address::Family family = table_->family();
190 
191  BgpMpNlri *nlri =
193  BgpAf::FamilyToAfi(family), BgpAf::FamilyToSafi(family));
194  update.path_attributes.push_back(nlri);
195 
196  BgpProtoPrefix *prefix = new BgpProtoPrefix;
197  route->BuildProtoPrefix(prefix);
198  nlri->nlri.push_back(prefix);
199 
200  int result =
201  BgpProto::Encode(&update, data_, sizeof(data_), &encode_offsets_);
202  if (result <= 0) {
203  BGP_LOG_WARNING_STR(BgpMessageSend, BGP_LOG_FLAG_ALL,
204  "Error encoding unreach message for route " << route->ToString() <<
205  " in table " << (table_ ? table_->name() : "unknown"));
207  return false;
208  }
209 
211  datalen_ = result;
212  return true;
213 }
214 
216  Message::Reset();
217  table_ = NULL;
219  datalen_ = 0;
220 }
221 
222 bool BgpMessage::Start(const RibOut *ribout, bool cache_repr,
223  const RibOutAttr *roattr, const BgpRoute *route) {
224  Reset();
225  table_ = ribout->table();
226 
227  if (roattr->IsReachable()) {
228  return StartReach(ribout, roattr, route);
229  } else {
230  return StartUnreach(route);
231  }
232 }
233 
234 bool BgpMessage::UpdateLength(const char *tag, int size, int delta) {
235  int offset = encode_offsets_.FindOffset(tag);
236  if (offset < 0) {
237  return false;
238  }
239  int value = get_value(&data_[offset], size);
240  value += delta;
241  put_value(&data_[offset], size, value);
242  return true;
243 }
244 
245 bool BgpMessage::AddRoute(const BgpRoute *route, const RibOutAttr *roattr) {
246  uint8_t *data = data_ + datalen_;
247  size_t size = sizeof(data_) - datalen_;
248  Address::Family family = table_->family();
249 
250  BgpMpNlri nlri;
251  nlri.afi = BgpAf::FamilyToAfi(family);
252  nlri.safi = BgpAf::FamilyToSafi(family);
253  BgpProtoPrefix *prefix = new BgpProtoPrefix;
254  if (roattr) {
255  const uint32_t label = (family == Address::INET) ? 0 : roattr->label();
256  route->BuildProtoPrefix(prefix, roattr->attr(), label);
257  } else {
258  route->BuildProtoPrefix(prefix);
259  }
260  nlri.nlri.push_back(prefix);
261 
262  int result = BgpProto::Encode(&nlri, data, size);
263  if (result <= 0) {
264  return false;
265  }
266 
267  datalen_ += result;
268  if (roattr->IsReachable()) {
270  } else {
272  }
273 
274  if (!UpdateLength("BgpMsgLength", 2, result)) {
275  assert(false);
276  return false;
277  }
278 
279  if (!UpdateLength("BgpPathAttribute", 2, result)) {
280  assert(false);
281  return false;
282  }
283 
284  if (!UpdateLength("MpReachUnreachNlri", 2, result)) {
285  assert(false);
286  return false;
287  }
288 
289  return true;
290 }
291 
293 }
294 
295 const uint8_t *BgpMessage::GetData(IPeerUpdate *peer, size_t *lenp,
296  const string **msg_str, string *temp) {
297  *lenp = datalen_;
298  return data_;
299 }
300 
302  return new BgpMessage;
303 }
304 
306 : MessageBuilder() {
307 }
const Community * community() const
Definition: bgp_attr.h:914
const std::vector< uint32_t > & communities() const
Definition: community.h:65
std::vector< OriginVnValue > OriginVnList
uint16_t afi
Definition: bgp_attr.h:307
const ClusterListSpec & cluster_list() const
Definition: bgp_attr.h:229
std::vector< BgpProtoPrefix * > nlri
Definition: bgp_attr.h:311
BgpTable * table()
Definition: bgp_ribout.h:304
uint32_t local_pref() const
Definition: bgp_attr.h:889
const IpAddress & nexthop() const
Definition: bgp_attr.h:886
const BgpAttr * attr() const
Definition: bgp_ribout.h:97
const AsPathSpec & path() const
Definition: bgp_aspath.h:127
const EdgeForwardingSpec & edge_forwarding() const
Definition: bgp_attr.h:577
bool as4_supported() const
Definition: bgp_ribout.h:325
Family
Definition: address.h:24
virtual Message * Create() const
virtual void BuildProtoPrefix(BgpProtoPrefix *prefix, const BgpAttr *attr=NULL, uint32_t label=0, uint32_t l3_label=0) const
Definition: bgp_route.h:66
BgpProto::BgpPeerType peer_type() const
Definition: bgp_ribout.h:320
uint8_t data_[BgpProto::kMaxMessageSize]
const OriginVnPath * origin_vn_path() const
Definition: bgp_attr.h:916
bool StartUnreach(const BgpRoute *route)
const Ip4Address & originator_id() const
Definition: bgp_attr.h:895
const IpAddress & aggregator_adderess() const
Definition: bgp_attr.h:894
uint64_t num_unreach_route_
bool StartReach(const RibOut *ribout, const RibOutAttr *roattr, const BgpRoute *route)
virtual Address::Family family() const =0
static uint64_t get_value(const uint8_t *data, int size)
Definition: parse_object.h:39
virtual const uint8_t * GetData(IPeerUpdate *peer, size_t *lenp, const std::string **msg_str, std::string *temp)
static Safi FamilyToSafi(Address::Family family)
Definition: bgp_af.cc:188
virtual void Reset()
const AsPath4Byte * aspath_4byte() const
Definition: bgp_attr.h:902
static int Encode(const BgpMessage *msg, uint8_t *data, size_t size, EncodeOffsets *offsets=NULL, bool as4=false)
Definition: bgp_proto.cc:2107
const ClusterList * cluster_list() const
Definition: bgp_attr.h:907
const ExtCommunityList & communities() const
Definition: community.h:180
virtual void BuildBgpProtoNextHop(std::vector< uint8_t > &nh, IpAddress nexthop) const
Definition: bgp_route.h:71
void ClearOffsets()
Definition: parse_object.h:97
uint64_t num_reach_route_
bool UpdateLength(const char *tag, int size, int delta)
virtual std::string ToString() const =0
const std::string & name() const
Definition: db_table.h:110
const BgpTable * table_
as_t aggregator_as_num() const
Definition: bgp_attr.h:891
std::vector< uint64_t > origin_vns
const EdgeDiscoverySpec & edge_discovery() const
Definition: bgp_attr.h:470
uint32_t l3_label() const
Definition: bgp_ribout.h:118
const As4Path * as4_path() const
Definition: bgp_attr.h:911
bool IsReachable() const
Definition: bgp_ribout.h:94
EncodeOffsets encode_offsets_
#define BGP_LOG_WARNING_STR(obj, flags, arg)
Definition: bgp_log.h:107
const AsPath * as_path() const
Definition: bgp_attr.h:899
virtual bool AddRoute(const BgpRoute *route, const RibOutAttr *roattr)
static Afi FamilyToAfi(Address::Family family)
Definition: bgp_af.cc:159
BgpServer * server()
Definition: bgp_table.cc:88
uint32_t label() const
Definition: bgp_ribout.h:115
const ExtCommunity * ext_community() const
Definition: bgp_attr.h:915
uint8_t safi
Definition: bgp_attr.h:308
const OriginVnList & origin_vns() const
const AsPath4ByteSpec & path() const
Definition: bgp_aspath.h:285
virtual ~BgpMessage()
BgpAttrOrigin::OriginType origin() const
Definition: bgp_attr.h:881
std::vector< ExtCommunityValue > ExtCommunityList
Definition: community.h:153
virtual bool Start(const RibOut *ribout, bool cache_routes, const RibOutAttr *roattr, const BgpRoute *route)
const PmsiTunnelSpec & pmsi_tunnel() const
Definition: bgp_attr.h:373
const EdgeForwarding * edge_forwarding() const
Definition: bgp_attr.h:921
const As4PathSpec & path() const
Definition: bgp_aspath.h:443
virtual void Reset()
std::vector< uint32_t > communities
Definition: community.h:33
const EdgeDiscovery * edge_discovery() const
Definition: bgp_attr.h:918
std::vector< uint64_t > communities
Definition: community.h:143
uint32_t med() const
Definition: bgp_attr.h:888
const PmsiTunnel * pmsi_tunnel() const
Definition: bgp_attr.h:917
#define AS_TRANS
Definition: bgp_common.h:23
bool atomic_aggregate() const
Definition: bgp_attr.h:890
void increment_message_build_error() const
Definition: bgp_server.h:269
std::vector< BgpAttribute * > path_attributes
Definition: bgp_proto.h:435
#define BGP_LOG_FLAG_ALL
Definition: bgp_log.h:44
virtual void Finish()
static void put_value(uint8_t *data, int size, uint64_t value)
Definition: parse_object.h:55