backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / lib / packet / packet_utils.py
1 # Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import array
17 import six
18 import socket
19 import struct
20 from ryu.lib import addrconv
21
22
23 def carry_around_add(a, b):
24     c = a + b
25     return (c & 0xffff) + (c >> 16)
26
27
28 def checksum(data):
29     data = six.binary_type(data)    # input can be bytearray.
30     if len(data) % 2:
31         data += b'\x00'
32
33     s = sum(array.array('H', data))
34     s = (s & 0xffff) + (s >> 16)
35     s += (s >> 16)
36     return socket.ntohs(~s & 0xffff)
37
38
39 # avoid circular import
40 _IPV4_PSEUDO_HEADER_PACK_STR = '!4s4sxBH'
41 _IPV6_PSEUDO_HEADER_PACK_STR = '!16s16sI3xB'
42
43
44 def checksum_ip(ipvx, length, payload):
45     """
46     calculate checksum of IP pseudo header
47
48     IPv4 pseudo header
49     UDP RFC768
50     TCP RFC793 3.1
51
52      0      7 8     15 16    23 24    31
53     +--------+--------+--------+--------+
54     |          source address           |
55     +--------+--------+--------+--------+
56     |        destination address        |
57     +--------+--------+--------+--------+
58     |  zero  |protocol|    length       |
59     +--------+--------+--------+--------+
60
61
62     IPv6 pseudo header
63     RFC2460 8.1
64     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65     |                                                               |
66     +                                                               +
67     |                                                               |
68     +                         Source Address                        +
69     |                                                               |
70     +                                                               +
71     |                                                               |
72     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73     |                                                               |
74     +                                                               +
75     |                                                               |
76     +                      Destination Address                      +
77     |                                                               |
78     +                                                               +
79     |                                                               |
80     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81     |                   Upper-Layer Packet Length                   |
82     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83     |                      zero                     |  Next Header  |
84     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85     """
86     if ipvx.version == 4:
87         header = struct.pack(_IPV4_PSEUDO_HEADER_PACK_STR,
88                              addrconv.ipv4.text_to_bin(ipvx.src),
89                              addrconv.ipv4.text_to_bin(ipvx.dst),
90                              ipvx.proto, length)
91     elif ipvx.version == 6:
92         header = struct.pack(_IPV6_PSEUDO_HEADER_PACK_STR,
93                              addrconv.ipv6.text_to_bin(ipvx.src),
94                              addrconv.ipv6.text_to_bin(ipvx.dst),
95                              length, ipvx.nxt)
96     else:
97         raise ValueError('Unknown IP version %d' % ipvx.version)
98
99     buf = header + payload
100     return checksum(buf)
101
102
103 _MODX = 4102
104
105
106 def fletcher_checksum(data, offset):
107     """
108     Fletcher Checksum -- Refer to RFC1008
109
110     calling with offset == _FLETCHER_CHECKSUM_VALIDATE will validate the
111     checksum without modifying the buffer; a valid checksum returns 0.
112     """
113     c0 = 0
114     c1 = 0
115     pos = 0
116     length = len(data)
117     data = bytearray(data)
118     data[offset:offset + 2] = [0] * 2
119
120     while pos < length:
121         tlen = min(length - pos, _MODX)
122         for d in data[pos:pos + tlen]:
123             c0 += d
124             c1 += c0
125         c0 %= 255
126         c1 %= 255
127         pos += tlen
128
129     x = ((length - offset - 1) * c0 - c1) % 255
130     if x <= 0:
131         x += 255
132     y = 510 - c0 - x
133     if y > 255:
134         y -= 255
135
136     data[offset] = x
137     data[offset + 1] = y
138     return (x << 8) | (y & 0xff)