File Coverage

blib/lib/NetPacket/LACP.pm
Criterion Covered Total %
statement 18 65 27.6
branch 0 6 0.0
condition n/a
subroutine 6 12 50.0
pod 4 5 80.0
total 28 88 31.8


line stmt bran cond sub pod time code
1             #
2             # NetPacket::LACP - Decode and encode Link Aggregation Control Protocol
3             # packets
4             #
5             # Comments/suggestions to cganesan@cpan.org
6             #
7              
8             package NetPacket::LACP;
9              
10             #
11             # Copyright (c) 2002 Chander Ganesan.
12             #
13             # This package is free software and is provided "as is" without express
14             # or implied warranty. It may be used, redistributed and/or modified
15             # under the terms of the Perl Artistic License (see
16             # http://www.perl.com/perl/misc/Artistic.html)
17             #
18             # This software and all associated data and documentation
19             # ('Software') is available free of charge. You may make copies of the
20             # Software but you must include all of this notice on any copy.
21             #
22             # The Software was developed for research purposes does not
23             # warrant that it is error free or fit for any purpose. The author
24             # disclaims any liability for all claims, expenses, losses, damages
25             # and costs any user may incur as a result of using, copying or
26             # modifying the Software.
27             #
28              
29 1     1   13506 use 5.006;
  1         4  
  1         54  
30 1     1   7 use strict;
  1         2  
  1         41  
31 1     1   8 use warnings;
  1         8  
  1         58  
32 1     1   6 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  1         2  
  1         149  
33              
34             my $myclass;
35             BEGIN {
36 1     1   2 $myclass = __PACKAGE__;
37 1         331 $VERSION = "0.01";
38             }
39 0     0 1   sub Version () { "$myclass v$VERSION" }
40              
41             BEGIN {
42 1     1   25 @ISA = qw(Exporter NetPacket);
43              
44             # Items to export into callers namespace by default
45             # (move infrequently used names to @EXPORT_OK below)
46              
47 1         3 @EXPORT = qw(
48             );
49              
50             # Other items we are prepared to export if requested
51              
52 1         3 @EXPORT_OK = qw(lacp_strip
53             );
54              
55             # Tags:
56              
57 1         1186 %EXPORT_TAGS = (
58             ALL => [@EXPORT, @EXPORT_OK],
59             strip => [qw(lacp_strip)],
60             types => [qw(
61             )],
62             );
63              
64             }
65              
66             #
67             # Decode the packet
68             #
69              
70             sub decode {
71 0     0 1   my $class = shift;
72 0           my($pkt, $parent, @rest) = @_;
73 0           my $self = {};
74              
75             # Class fields
76              
77 0           $self->{_parent} = $parent;
78 0           $self->{_frame} = $pkt;
79              
80             # Decode LACP packet
81              
82             #
83             # Here's the format of the packet. We can pass this in to unpack to
84             # unpack it...
85             #
86              
87             #
88             # Perform hex to decimal conversions on these fields..
89             #
90 0           my @convert_from_hex = qw(version partner_info_length
91             collector_info_length
92             actor_info_length);
93 0           my $lacp_contents = _get_decoder();
94            
95 0 0         if (defined($pkt)) {
96 0           my ($key, $rest);
97 0           $rest = $pkt;
98 0           foreach $key (sort numerically keys %$lacp_contents) {
99 0           foreach (keys %{$lacp_contents->{$key}}) {
  0            
100 0           ($self->{$_}, $rest) = unpack($lacp_contents->{$key}{$_} .
101             "a*", $rest);
102             }
103             }
104              
105              
106 0           ($self->{AS_expired},
107             $self->{AS_defaulted},
108             $self->{AS_distributing},
109             $self->{AS_collecting},
110             $self->{AS_synchronization},
111             $self->{AS_aggregation},
112             $self->{AS_lacp_timeout},
113             $self->{AS_lacp_activity}) = split "", $self->{AS};
114              
115            
116 0           ($self->{PS_expired},
117             $self->{PS_defaulted},
118             $self->{PS_distributing},
119             $self->{PS_collecting},
120             $self->{PS_synchronization},
121             $self->{PS_aggregation},
122             $self->{PS_lacp_timeout},
123             $self->{PS_lacp_activity}) = split "", $self->{PS};
124              
125             #
126             # Perform hex to decimal conversion where necessary.
127             #
128              
129 0           foreach (@convert_from_hex) {
130 0           $self->{$_} = hex($self->{$_});
131             }
132             }
133             # Return a blessed object
134 0 0         return undef unless ($self->{version} == 1); # Verion 1 is LACP..
135 0           bless($self, $class);
136 0           return $self;
137             }
138              
139             #
140             # Strip header from packet and return the data contained in it. Spanning
141             # Tree packets contain no encapsulated data.
142             #
143              
144             undef &lacp_strip; # Create st_strip alias
145             *lacp_strip = \&strip;
146              
147             sub strip {
148 0     0 1   return undef;
149             }
150              
151             #
152             # Encode a packet
153             #
154              
155             sub encode {
156 0     0 1   my ($class, $data)= @_;
157 0           my $self = {};
158 0           my $pkt;
159             # Encode LACP packet
160              
161             #
162             # Set some sensible defaults
163             #
164 0           my $defaults = {
165             'lacp' => '01' ,
166             'version' => '01' ,
167             'actor_info' => '01' ,
168             'actor_info_length' => '20' ,
169             'actor_system_priority' => '25600' ,
170             'actor_system' => '000000000000' ,
171             'actor_key' => '193' ,
172             'actor_port_priority' => '0' ,
173             'actor_port' => '1' ,
174             'reserved_1' => '0' x 6 ,
175             'partner_info' => '02' ,
176             'partner_info_length' => '20' ,
177             'partner_system_priority' => '0' ,
178             'partner_system' => '000000000000' ,
179             'partner_key' => '0' ,
180             'partner_port_priority' => '0' ,
181             'partner_port' => '1' ,
182             'reserved_2' => '0' x 6 ,
183             'collector_info' => '03' ,
184             'collector_info_length' => '16' ,
185             'collector_max_delay' => '10000' ,
186             'reserved_3' => '0' x 24 ,
187             'terminator_info' => '00' ,
188             'terminator_length' => '00' ,
189             'reserved_4' => '0' x 100,
190             };
191              
192 0           foreach (keys %$defaults) {
193 0 0         if (! defined $data->{$_}) {
194 0           $data->{$_} = $defaults->{$_};
195             }
196             }
197             #
198             # Perform decimal to hex conversions on these fields..
199             #
200 0           my @convert_from_hex = qw(version partner_info_length
201             collector_info_length
202             actor_info_length);
203 0           my $lacp_contents = _get_decoder();
204            
205             #
206             # Perform decimal to hex conversion where necessary.
207             #
208 0           foreach (@convert_from_hex) {
209 0           $data->{$_} = sprintf("%02lx", $data->{$_});
210             }
211            
212 0           $data->{AS} = join "", $data->{AS_expired},
213             $data->{AS_defaulted},
214             $data->{AS_distributing},
215             $data->{AS_collecting},
216             $data->{AS_synchronization},
217             $data->{AS_aggregation},
218             $data->{AS_lacp_timeout},
219             $data->{AS_lacp_activity};
220              
221              
222 0           $data->{PS} = join "", $data->{PS_expired},
223             $data->{PS_defaulted},
224             $data->{PS_distributing},
225             $data->{PS_collecting},
226             $data->{PS_synchronization},
227             $data->{PS_aggregation},
228             $data->{PS_lacp_timeout},
229             $data->{PS_lacp_activity};
230            
231             #
232             # Encode the data...
233             #
234              
235 0           my ($key, $rest);
236 0           $rest = $pkt;
237 0           foreach $key (sort numerically keys %$lacp_contents) {
238 0           foreach (keys %{$lacp_contents->{$key}}) {
  0            
239 0           $pkt .= pack($lacp_contents->{$key}{$_},
240             $data->{$_});
241             }
242             }
243              
244             #
245             # Perform hex to decimal conversion where necessary.
246             #
247 0           foreach (@convert_from_hex) {
248 0           $data->{$_} = hex($data->{$_});
249             }
250 0           return $pkt;
251             }
252              
253             sub _get_decoder {
254             return {
255 0     0     0 => { 'lacp' => 'H2' },
256             1 => { 'version' => 'H2' },
257             2 => { 'actor_info' => 'H2' },
258             3 => { 'actor_info_length' => 'H2' },
259             4 => { 'actor_system_priority' => 'n' },
260             5 => { 'actor_system' => 'H12' },
261             6 => { 'actor_key' => 'n' },
262             7 => { 'actor_port_priority' => 'n' },
263             8 => { 'actor_port' => 'n' },
264             10 => { 'AS' => 'B8' },
265             17 => { 'reserved_1' => 'H6' },
266             18 => { 'partner_info' => 'H2' },
267             19 => { 'partner_info_length' => 'H2' },
268             20 => { 'partner_system_priority' => 'n' },
269             21 => { 'partner_system' => 'H12' },
270             22 => { 'partner_key' => 'n' },
271             23 => { 'partner_port_priority' => 'n' },
272             24 => { 'partner_port' => 'n' },
273             25 => { 'PS' => 'B8' },
274             33 => { 'reserved_2' => 'H6' },
275             34 => { 'collector_info' => 'H2' },
276             35 => { 'collector_info_length' => 'H2' },
277             36 => { 'collector_max_delay' => 'n' },
278             37 => { 'reserved_3' => 'H24' },
279             38 => { 'terminator_info' => 'H2' },
280             39 => { 'terminator_length' => 'H2' },
281             40 => { 'reserved_4' => 'H100' },
282             };
283             }
284             #
285             # provided for sorting.
286             #
287             sub numerically {
288 0     0 0   $a <=> $b;
289             }
290              
291              
292             #
293             # Module return value
294             #
295             1;
296              
297             # autoloaded methods go after the END token (&& pod) below
298              
299             __END__