bgp4r 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bgp/common.rb +14 -13
- data/bgp/iana.rb +26 -1
- data/bgp/messages/capability.rb +3 -2
- data/bgp/messages/message.rb +3 -2
- data/bgp/messages/open.rb +2 -1
- data/bgp/messages/update.rb +80 -30
- data/bgp/neighbor/add_path_cap.rb +125 -0
- data/bgp/{neighbor.rb → neighbor/neighbor.rb} +64 -68
- data/bgp/nlris/nlri.rb +289 -15
- data/bgp/nlris/prefix.rb +3 -2
- data/bgp/nlris/vpn.rb +1 -8
- data/bgp/optional_parameters/add_path.rb +160 -0
- data/bgp/optional_parameters/capabilities.rb +1 -0
- data/bgp/optional_parameters/capability.rb +6 -0
- data/bgp/optional_parameters/graceful_restart.rb +6 -6
- data/bgp/optional_parameters/optional_parameter.rb +1 -0
- data/bgp/path_attributes/as_path.rb +1 -1
- data/bgp/path_attributes/attribute.rb +12 -5
- data/bgp/path_attributes/mp_reach.rb +142 -96
- data/bgp/path_attributes/mp_unreach.rb +73 -20
- data/bgp/path_attributes/path_attribute.rb +28 -5
- data/bgp4r.gemspec +21 -6
- data/bgp4r.rb +1 -1
- data/examples/unit-testing/malformed_update.rb +2 -1
- data/examples/unit-testing/test.rb +82 -0
- data/examples/unit-testing/test1.rb +82 -0
- data/examples/unit-testing/test2.rb +44 -0
- data/test/common_test.rb +7 -0
- data/test/helpers/server.rb +20 -0
- data/test/iana_test.rb +43 -0
- data/test/messages/open_test.rb +7 -2
- data/test/messages/update_test.rb +133 -36
- data/test/neighbor/add_path_cap_test.rb +54 -0
- data/test/neighbor/neighbor_test.rb +161 -0
- data/test/nlris/ext_nlri_test.rb +25 -60
- data/test/nlris/nlri_test.rb +93 -115
- data/test/optional_parameters/add_path_test.rb +53 -0
- data/test/optional_parameters/capability_test.rb +10 -0
- data/test/optional_parameters/graceful_restart_test.rb +1 -0
- data/test/path_attributes/mp_reach_test.rb +206 -8
- data/test/path_attributes/mp_unreach_test.rb +113 -5
- data/test/path_attributes/path_attribute_test.rb +34 -2
- metadata +20 -7
- data/test/neighbor_test.rb +0 -62
@@ -0,0 +1,160 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2010 Jean-Michel Esnault.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# This file is part of BGP4R.
|
8
|
+
#
|
9
|
+
# BGP4R is free software: you can redistribute it and/or modify
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
12
|
+
# (at your option) any later version.
|
13
|
+
#
|
14
|
+
# BGP4R is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
# GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License
|
20
|
+
# along with BGP4R. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#++
|
22
|
+
|
23
|
+
require 'bgp/optional_parameters/capability'
|
24
|
+
|
25
|
+
module BGP::OPT_PARM::CAP
|
26
|
+
|
27
|
+
#
|
28
|
+
# Belongs to Neighbor this is a session attribute....
|
29
|
+
# def include_path_id?(speeker, peer, sr, afi, safi)
|
30
|
+
# # when sending afi, safi, speaker agrees to send and peer to receive
|
31
|
+
# # when receiving afi, safi, speaker agrees to recv and peer agress to send
|
32
|
+
# case sr
|
33
|
+
# when :recv
|
34
|
+
# speeker.has?(:recv, afi, safi) && peer.has?(:send, afi, safi)
|
35
|
+
# when :send
|
36
|
+
# speeker.has?(:send, afi, safi) && peer.has?(:recv, afi, safi)
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
|
40
|
+
class Add_path < BGP::OPT_PARM::Capability
|
41
|
+
|
42
|
+
class << self
|
43
|
+
def new_array(arg)
|
44
|
+
o = new
|
45
|
+
arg.each { |t| o.add(*t) }
|
46
|
+
o
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize(*args)
|
51
|
+
@af={}
|
52
|
+
if args.size>1
|
53
|
+
super(OPT_PARM::CAP_ADD_PATH)
|
54
|
+
add(*args)
|
55
|
+
elsif args.size==1 and args[0].is_a?(String)
|
56
|
+
parse(*args)
|
57
|
+
elsif args.empty?
|
58
|
+
super(OPT_PARM::CAP_ADD_PATH)
|
59
|
+
else
|
60
|
+
raise
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def add(sr, afi,safi)
|
65
|
+
@af[[_afi(afi), _safi(safi)]] = _send_recv(sr)
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse(s)
|
69
|
+
families = super(s)
|
70
|
+
while families.size>0
|
71
|
+
afi, safi, sr = families.slice!(0,4).unpack('nCC')
|
72
|
+
@af[[afi,safi]]=sr
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# 0001 01 01
|
77
|
+
# 0002 80 02
|
78
|
+
# 0002 01 03
|
79
|
+
|
80
|
+
def send? afi, safi
|
81
|
+
has? :send, afi, safi
|
82
|
+
end
|
83
|
+
|
84
|
+
def recv? afi, safi
|
85
|
+
has? :recv, afi, safi
|
86
|
+
end
|
87
|
+
|
88
|
+
def has?(sr, afi, safi)
|
89
|
+
case sr
|
90
|
+
when :recv
|
91
|
+
@af.has_key?([afi,safi]) && (2..3) === @af[[afi,safi]]
|
92
|
+
when :send
|
93
|
+
@af.has_key?([afi,safi]) && (@af[[afi,safi]] == 1 or @af[[afi,safi]] ==3)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def encode
|
98
|
+
s = []
|
99
|
+
s << @af.to_a.sort.collect { |e| e.flatten.pack('nCC') }
|
100
|
+
super s.join
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_s
|
104
|
+
s = []
|
105
|
+
s << "\n Add-path Extension (#{CAP_ADD_PATH}), length: #{encode.size}"
|
106
|
+
s = s.join("\n ")
|
107
|
+
super + (s + (['']+@af.to_a.collect { |e| address_family_to_s(*e)}).join("\n "))
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def address_family_to_s(af, sr)
|
113
|
+
afi, safi = af
|
114
|
+
"AFI #{IANA.afi(afi)} (#{afi}), SAFI #{IANA.safi(safi)} (#{safi}), #{send_recv_to_s(sr)}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def _send_recv(val)
|
118
|
+
case val
|
119
|
+
when :send, 1 ; 1
|
120
|
+
when :recv, :receive, 2 ; 2
|
121
|
+
when :send_and_recv, :send_recv, :send_and_receive, 3 ; 3
|
122
|
+
else
|
123
|
+
val
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def send_recv_to_s(val)
|
128
|
+
case val
|
129
|
+
when 1 ; 'SEND (1)'
|
130
|
+
when 2 ; 'RECV (2)'
|
131
|
+
when 3 ; 'SEND_AND_RECV (3)'
|
132
|
+
else
|
133
|
+
'bogus'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def _afi(val)
|
138
|
+
if val.is_a?(Fixnum)
|
139
|
+
val
|
140
|
+
elsif val == :ipv4
|
141
|
+
1
|
142
|
+
elsif val == :ipv6
|
143
|
+
2
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def _safi(val)
|
148
|
+
if val.is_a?(Fixnum)
|
149
|
+
val
|
150
|
+
elsif val == :unicast
|
151
|
+
1
|
152
|
+
elsif val == :multicast
|
153
|
+
2
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
load "../../test/optional_parameters/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
@@ -7,6 +7,7 @@ require 'bgp/optional_parameters/optional_parameter'
|
|
7
7
|
require 'bgp/optional_parameters/orf'
|
8
8
|
require 'bgp/optional_parameters/route_refresh'
|
9
9
|
require 'bgp/optional_parameters/as4'
|
10
|
+
require 'bgp/optional_parameters/add_path'
|
10
11
|
|
11
12
|
module BGP::OPT_PARM
|
12
13
|
module DYN_CAP
|
@@ -114,6 +114,8 @@ module BGP::OPT_PARM
|
|
114
114
|
CAP::Orf.new(s)
|
115
115
|
when CAP_GR
|
116
116
|
CAP::Graceful_restart.new(s)
|
117
|
+
when CAP_ADD_PATH
|
118
|
+
CAP::Add_path.new(s)
|
117
119
|
when CAP_DYNAMIC
|
118
120
|
CAP::Dynamic.new(s)
|
119
121
|
else
|
@@ -134,8 +136,12 @@ module BGP::OPT_PARM
|
|
134
136
|
DYN_CAP::Route_refresh.new(code)
|
135
137
|
when CAP_ORF,CAP_ORF_CISCO
|
136
138
|
DYN_CAP::Orf.new(s)
|
139
|
+
when CAP_ADD_PATH
|
140
|
+
DYN_CAP::Add_path.new(s)
|
137
141
|
when CAP_GR
|
138
142
|
DYN_CAP::Graceful_restart.new(s)
|
143
|
+
when CAP_ADD_PATH
|
144
|
+
CAP::Add_path.new(s)
|
139
145
|
else
|
140
146
|
Capability::Unknown.new(s)
|
141
147
|
end
|
@@ -29,7 +29,7 @@ class Graceful_restart < BGP::OPT_PARM::Capability
|
|
29
29
|
def initialize(*args)
|
30
30
|
if args.size>1
|
31
31
|
@restart_state, @restart_time = args
|
32
|
-
@
|
32
|
+
@tuples = []
|
33
33
|
super(OPT_PARM::CAP_GR)
|
34
34
|
else
|
35
35
|
parse(*args)
|
@@ -37,16 +37,16 @@ class Graceful_restart < BGP::OPT_PARM::Capability
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def add(afi,safi,flags)
|
40
|
-
@
|
40
|
+
@tuples << [_afi(afi), _safi(safi), flags]
|
41
41
|
end
|
42
42
|
|
43
43
|
def parse(s)
|
44
|
-
@
|
44
|
+
@tuples = []
|
45
45
|
o1, families = super(s).unpack('na*')
|
46
46
|
@restart_state = o1 >> 12
|
47
47
|
@restart_time = o1 & 0xfff
|
48
48
|
while families.size>0
|
49
|
-
@
|
49
|
+
@tuples << families.slice!(0,4).unpack('nCC')
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -54,7 +54,7 @@ class Graceful_restart < BGP::OPT_PARM::Capability
|
|
54
54
|
def encode
|
55
55
|
s = []
|
56
56
|
s << [(@restart_state << 12) + @restart_time].pack('n')
|
57
|
-
s << @
|
57
|
+
s << @tuples.collect { |af| af.pack('nCC') }
|
58
58
|
super s.join
|
59
59
|
end
|
60
60
|
def to_s
|
@@ -62,7 +62,7 @@ class Graceful_restart < BGP::OPT_PARM::Capability
|
|
62
62
|
s << "\n Graceful Restart Extension (#{CAP_GR}), length: 4"
|
63
63
|
s << " Restart Flags: #{restart_flag}, Restart Time #{@restart_time}s"
|
64
64
|
s = s.join("\n ")
|
65
|
-
super + (s + (['']+@
|
65
|
+
super + (s + (['']+@tuples.collect { |af| address_family(*af)}).join("\n "))
|
66
66
|
end
|
67
67
|
|
68
68
|
private
|
@@ -61,16 +61,23 @@ module BGP
|
|
61
61
|
OPTIONAL_TRANSITIVE = OPTIONAL | TRANSITIVE
|
62
62
|
OPTIONAL_NON_TRANSITIVE = OPTIONAL
|
63
63
|
|
64
|
-
def
|
65
|
-
len, len_fmt = value.size, 'C'
|
64
|
+
def len_fmt(len)
|
66
65
|
if len>255
|
67
66
|
@flags |= EXTENDED_LENGTH
|
68
|
-
|
67
|
+
@_len_fmt='n'
|
68
|
+
else
|
69
|
+
@_len_fmt = 'C'
|
70
|
+
@flags &= ~EXTENDED_LENGTH
|
69
71
|
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def encode(value='',value_fmt=nil)
|
75
|
+
len = value.size
|
76
|
+
len_fmt(len)
|
70
77
|
if value_fmt
|
71
|
-
[@flags<<4, @type, len, *value].pack("CC#{
|
78
|
+
[@flags<<4, @type, len, *value].pack("CC#{@_len_fmt}#{value_fmt}")
|
72
79
|
else
|
73
|
-
([@flags<<4, @type, len].pack("CC#{
|
80
|
+
([@flags<<4, @type, len].pack("CC#{@_len_fmt}") + value).is_packed
|
74
81
|
end
|
75
82
|
end
|
76
83
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#--
|
1
|
+
#--
|
2
2
|
# Copyright 2008, 2009 Jean-Michel Esnault.
|
3
3
|
# All rights reserved.
|
4
4
|
# See LICENSE.txt for permissions.
|
@@ -24,119 +24,165 @@ require 'bgp/path_attributes/attribute'
|
|
24
24
|
require 'bgp/nlris/nlris'
|
25
25
|
|
26
26
|
module BGP
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
27
|
+
|
28
|
+
class Mp_reach < Attr
|
29
|
+
|
30
|
+
attr_reader :safi, :nlris, :path_id
|
31
|
+
|
32
|
+
def initialize(*args)
|
33
|
+
@safi, @nexthops, @nlris, @path_id= 1, [], [], nil # default is ipv4/unicast
|
34
|
+
@flags, @type = OPTIONAL, MP_REACH
|
35
|
+
if args[0].is_a?(String) and args[0].is_packed?
|
36
|
+
parse(*args)
|
37
|
+
elsif args[0].is_a?(self.class)
|
38
|
+
s = args.shift.encode
|
39
|
+
parse(s, *args)
|
40
|
+
elsif args[0].is_a?(Hash) and args.size==1
|
41
|
+
set(*args)
|
42
|
+
else
|
43
|
+
raise ArgumentError, "invalid argument"
|
44
44
|
end
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
end
|
46
|
+
|
47
|
+
def afi
|
48
|
+
@afi ||= @nexthops[0].afi
|
49
|
+
end
|
50
|
+
|
51
|
+
def set(h)
|
52
|
+
@safi = h[:safi]
|
53
|
+
@path_id = path_id = h[:path_id]
|
54
|
+
case @safi
|
55
|
+
when 1,2,4 ; @nexthops = [h[:nexthop]].flatten.collect { |nh| Prefix.new(nh) }
|
56
|
+
when 128,129 ; @nexthops = [h[:nexthop]].flatten.collect { |nh| Vpn.new(nh) }
|
57
|
+
else
|
48
58
|
end
|
49
|
-
|
50
|
-
|
51
|
-
@
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
59
|
+
case @safi
|
60
|
+
when 1
|
61
|
+
@nlris = [h[:nlris]].flatten.collect do |n|
|
62
|
+
case n
|
63
|
+
when String
|
64
|
+
nlri = Inet_unicast.new(n)
|
65
|
+
path_id ? Ext_Nlri.new(path_id, nlri) : nlri
|
66
|
+
when Hash
|
67
|
+
path_id = n[:path_id] if n[:path_id]
|
68
|
+
nlri = Inet_unicast.new(n[:prefix])
|
69
|
+
path_id ? Ext_Nlri.new(path_id, nlri) : nlri
|
70
|
+
else
|
71
|
+
raise ArgumentError, "Invalid: #{n.inspect}"
|
72
|
+
end
|
56
73
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
74
|
+
when 2
|
75
|
+
@nlris = [h[:nlris]].flatten.collect do |n|
|
76
|
+
case n
|
77
|
+
when String
|
78
|
+
nlri = Inet_multicast.new(n)
|
79
|
+
path_id ? Ext_Nlri.new(path_id, nlri) : nlri
|
80
|
+
when Hash
|
81
|
+
path_id = n[:path_id] if n[:path_id]
|
82
|
+
nlri = Inet_multicast.new(n[:prefix])
|
83
|
+
path_id ? Ext_Nlri.new(path_id, nlri) : nlri
|
84
|
+
else
|
85
|
+
raise ArgumentError, "Invalid: #{n.inspect}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
when 4
|
89
|
+
@nlris = [h[:nlris]].flatten.collect do |n|
|
90
|
+
path_id = n[:path_id] || @path_id
|
91
|
+
prefix = n[:prefix].is_a?(String) ? Prefix.new(n[:prefix]) : n[:prefix]
|
92
|
+
nlri = Labeled.new(prefix, *n[:label])
|
93
|
+
path_id ? Ext_Nlri.new(path_id, nlri) : nlri
|
94
|
+
end
|
95
|
+
when 128,129
|
96
|
+
@nlris = [h[:nlris]].flatten.collect do |n|
|
97
|
+
path_id = n[:path_id] || @path_id
|
66
98
|
prefix = n[:prefix].is_a?(Prefix) ? n[:prefix] : Prefix.new(n[:prefix])
|
67
99
|
rd = n[:rd].is_a?(Rd) ? n[:rd] : Rd.new(*n[:rd])
|
68
|
-
Labeled.new(Vpn.new(prefix,rd), *n[:label])
|
69
|
-
|
100
|
+
nlri = Labeled.new(Vpn.new(prefix,rd), *n[:label])
|
101
|
+
path_id ? Ext_Nlri.new(path_id, nlri) : nlri
|
70
102
|
end
|
103
|
+
else
|
71
104
|
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def nexthops
|
108
|
+
@nexthops.collect { |nh| nh.nexthop }.join(", ")
|
109
|
+
end
|
110
|
+
|
111
|
+
def mp_reach
|
112
|
+
"\n AFI #{IANA.afi(afi)} (#{afi}), SAFI #{IANA.safi(safi)} (#{safi})" +
|
113
|
+
"\n nexthop: " + nexthops +
|
114
|
+
(['']+ @nlris.collect { |nlri| nlri.to_s }).join("\n ")
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_s(method=:default)
|
118
|
+
super(mp_reach, method)
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_hash
|
122
|
+
end
|
123
|
+
|
124
|
+
def parse(s,arg=false)
|
72
125
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def mp_reach
|
78
|
-
"\n AFI #{IANA.afi(afi)} (#{afi}), SAFI #{IANA.safi(safi)} (#{safi})" +
|
79
|
-
"\n nexthop: " + nexthops +
|
80
|
-
(['']+ @nlris.collect { |nlri| nlri.to_s }).join("\n ")
|
81
|
-
end
|
82
|
-
|
83
|
-
def to_s(method=:default)
|
84
|
-
super(mp_reach, method)
|
85
|
-
end
|
126
|
+
@flags, @type, len, value = super(s)
|
127
|
+
@afi, @safi, nh_len = value.slice!(0,4).unpack('nCC')
|
128
|
+
parse_next_hops value.slice!(0,nh_len).is_packed
|
129
|
+
value.slice!(0,1)
|
86
130
|
|
87
|
-
|
131
|
+
if arg.respond_to?(:path_id?)
|
132
|
+
path_id_flag = arg.path_id? :recv, @afi, @safi
|
133
|
+
else
|
134
|
+
path_id_flag = arg
|
88
135
|
end
|
89
136
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
@nlris << Nlri.factory(value.slice!(0,(blen+7)/8+1), @afi, @safi)
|
137
|
+
while value.size>0
|
138
|
+
path_id = value.slice!(0,4).unpack('N')[0] if path_id_flag
|
139
|
+
blen = value.slice(0,1).unpack('C')[0]
|
140
|
+
nlri = Nlri.factory(value.slice!(0,(blen+7)/8+1), @afi, @safi)
|
141
|
+
if path_id_flag
|
142
|
+
@nlris << Ext_Nlri.new(path_id, nlri)
|
143
|
+
else
|
144
|
+
@nlris << nlri
|
99
145
|
end
|
100
|
-
raise RuntimeError, "leftover afer parsing: #{value.unpack('H*')}" if value.size>0
|
101
|
-
|
102
146
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
@nexthops << Vpn.new([64+32,s.slice!(0,12)].pack('Ca*'))
|
116
|
-
else
|
117
|
-
raise RuntimeError, "cannot parse nexthop for safi #{@safi}"
|
147
|
+
raise RuntimeError, "leftover afer parsing: #{value.unpack('H*')}" if value.size>0
|
148
|
+
end
|
149
|
+
|
150
|
+
def parse_next_hops(s)
|
151
|
+
while s.size>0
|
152
|
+
case @safi
|
153
|
+
when 1,2,4
|
154
|
+
case @afi
|
155
|
+
when 1
|
156
|
+
@nexthops << Prefix.new([32,s.slice!(0,4)].pack('Ca*'),1)
|
157
|
+
when 2
|
158
|
+
@nexthops << Prefix.new([128,s.slice!(0,16)].pack('Ca*'),2)
|
118
159
|
end
|
160
|
+
when 128,129
|
161
|
+
@nexthops << Vpn.new([64+32,s.slice!(0,12)].pack('Ca*'))
|
162
|
+
else
|
163
|
+
raise RuntimeError, "cannot parse nexthop for safi #{@safi}"
|
119
164
|
end
|
120
165
|
end
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
end
|
131
|
-
|
132
|
-
def new_unreach
|
133
|
-
s = encode(:mp_unreach)
|
134
|
-
s[1]= [MP_UNREACH].pack('C')
|
135
|
-
Mp_unreach.new(s)
|
166
|
+
end
|
167
|
+
|
168
|
+
def encode(what=:mp_reach)
|
169
|
+
case what
|
170
|
+
when :mp_reach
|
171
|
+
nexthops = @nexthops.collect { |nh| nh.encode(false) }.join
|
172
|
+
super([afi, @safi, nexthops.size, nexthops, 0, @nlris.collect { |n| n.encode }.join].pack('nCCa*Ca*'))
|
173
|
+
when :mp_unreach
|
174
|
+
super([afi, @safi, @nlris.collect { |n| n.encode }.join].pack('nCa*'))
|
136
175
|
end
|
137
|
-
|
138
176
|
end
|
139
|
-
|
177
|
+
|
178
|
+
def new_unreach
|
179
|
+
s = encode(:mp_unreach)
|
180
|
+
s[1]= [MP_UNREACH].pack('C')
|
181
|
+
Mp_unreach.new(s)
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
140
186
|
end
|
141
187
|
|
142
188
|
load "../../test/path_attributes/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|