summaryrefslogtreecommitdiff
path: root/maximus/python/maximus/ethernet/buffer.py
blob: 1b2f2b13af1a40a69e2bc36a5e1c65ad06bb6edf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#! usr/bin/env python

#print __name__

from maximus.macframe.msdu import MSDU_TYPES, MSDU
from maximus.utils.exception import Error, OutOfRangeError
from maximus.utils.format import *

# Constants to check arguments validity
MAX_VALUE_OF_BUFFER_NB = MAX_VALUE_OF_U32
SIZE_OF_BUFFER_ID = SIZE_OF_U32

class Buffer(MSDU):
    """The Buffer object is composed of the 6 following fields:
    buffer_id - the current buffer ID
    buffer_dict - the list of current allocated buffers (ID and type)
    buffer_realloc - indicates if buffer reallocation is automatic
    maximus - the Maximus object
    type - type of buffer
    buffer_nb - number of buffers to allocate
    """
    # Static attributes of the class
    buffer_id = 0
    buffer_dict = {}
    buffer_realloc = False
    __maximus = None

    def __init__(self, type, buffer_nb=1, maximus=None):
        """Initialize the Buffer with following attributes:
        type - a Python string
        buffer_nb - a Python integer
        maximus - the Maximus object
        """
        self.set_type(type)
        self.set_buffer_nb(buffer_nb)
        self.__set_maximus(maximus)

    def set_type(self, type):
        """This function sets the Buffer object type.
        The Buffer type can be a Python integer (u8)
        or a Python string equals to 'ETHERNET_TYPE_DATA_BUFFER_ADD',
        'ETHERNET_TYPE_MME_BUFFER_ADD',
        'ETHERNET_TYPE_INTERFACE_BUFFER_ADD',
        or 'ETHERNET_TYPE_BUFFER_RELEASED'.
        """
        self.__type = 0
        for i, j in enumerate(MSDU_TYPES):
            if type == i or type == j:
                self.__type = i
        if self.__type is None:
            raise OutOfRangeError("Buffer type")

    def set_buffer_nb(self, buffer_nb):
        """This function sets the number of buffers to allocate.
        The number of buffers must be a Python integer (u32).
        """
        self.__buffer_nb = 0
        if type(buffer_nb) is not int or buffer_nb <= 0 or buffer_nb > MAX_VALUE_OF_BUFFER_NB:
            raise OutOfRangeError("Number of buffers")
        else:
            self.__buffer_nb = buffer_nb

    def set_buffer_realloc(self, auto):
        """This function enables or disables the automatic buffer allocation.
        Auto must be a Python boolean.
        """
        if type(auto) is not bool:
            raise TypeError("Auto")
        else:
            self.__class__.buffer_realloc = auto

    def __set_maximus(self, maximus):
        """This function sets the Maximus object.
        """
        if maximus is not None and self.__class__.__maximus is None:
            self.__class__.__maximus = maximus

    def __inc_buffer_id(self):
        """This function increments the buffer ID (static attribute of the class).
        """
        self.__class__.buffer_id += 1

    def __add_buffer(self, id, type):
        """This function adds a buffer into the buffer dictionary (static attribute of the class).
        """
        self.__class__.buffer_dict[id] = type

    def __remove_buffer(self, id):
        """This function removes a buffer from the buffer dictionary (static attribute of the class).
        """
        del self.__class__.buffer_dict[id]

    def realloc(self, station_id, payload):
        """If requested by user, this function allocates a new buffer to replace released buffer.
        """
        from maximus.simu.rx import recv
        if self.get_buffer_realloc():
            if len(payload) != SIZE_OF_BUFFER_ID:
                raise Error('Buffer ID length')
            else:
                buffer = Buffer(type=self.__class__.buffer_dict[hptoh32(payload)], maximus=self.__get_maximus())
                # Request to Maximus to send the MSDU asynchronously
                while not self.__get_maximus().is_station_idle(station_id):
                    self.__get_maximus().process()
                self.__get_maximus().send_msdu(buffer, station_id)

    def set_msdu_attr(self, payload):
        """This function sets the MSDU attributes from the received Ethernet Frame.
        """
        if len(payload) != SIZE_OF_BUFFER_ID:
            raise Error('Buffer ID length')
        else:
            self.__remove_buffer(hptoh32(payload))

    def get(self):
        """This function returns the Buffer object into a string composed of the 2 following fields:
        number of buffers to allocate (u32)
        ID of each buffer to allocate (u32)
        """
        buffer = htohp32(self.get_buffer_nb())
        for n in range(0, self.get_buffer_nb()):
            self.__inc_buffer_id()
            buffer += htohp32(self.get_buffer_id())
            for i, j in enumerate(MSDU_TYPES):
                if self.get_ether_type() == i:
                    self.__add_buffer(self.get_buffer_id(), j)
        return buffer

    def get_ether_type(self):
        """This function returns the Buffer object type into a Python integer (u8).
        """
        return self.__type # 3, 4, 5 or 6

    def get_type(self):
        """This function returns the Buffer object type into a Python string.
        """
        return MSDU_TYPES[self.get_ether_type()] # 'ETHERNET_TYPE_DATA_BUFFER_ADD',
                                                 # 'ETHERNET_TYPE_MME_BUFFER_ADD',
                                                 # 'ETHERNET_TYPE_INTERFACE_BUFFER_ADD',
                                                 # or 'ETHERNET_TYPE_BUFFER_RELEASED'

    def get_buffer_nb(self):
        """This function gets the number of buffers to allocate.
        The number of buffers is a Python integer (u32).
        """
        return self.__buffer_nb

    def get_buffer_id(self):
        """This function returns the current buffer ID.
        """
        return self.__class__.buffer_id

    def get_buffer_dict(self):
        """This function returns the current buffer dictionary.
        """
        return self.__class__.buffer_dict

    def get_buffer_realloc(self):
        """This function gets if the current buffer reallocation is enabled or disabled.
        """
        return self.__class__.buffer_realloc

    def __get_maximus(self):
        """This function gets the Maximus object.
        """
        if self.__class__.__maximus is None:
            raise Error("Maximus object not set")
        return self.__class__.__maximus


def alloc_data_buffer(maximus, station, buffer_nb=1):
    buffer = Buffer(type='ETHERNET_TYPE_DATA_BUFFER_ADD', buffer_nb=buffer_nb, maximus=maximus)
    buffer.sendnrecv(maximus, station, count=0) # recv(maximus, count=0) to set creation functions

def alloc_mme_buffer(maximus, station, buffer_nb=1):
    buffer = Buffer(type='ETHERNET_TYPE_MME_BUFFER_ADD', buffer_nb=buffer_nb, maximus=maximus)
    buffer.sendnrecv(maximus, station, count=0) # recv(maximus, count=0) to set creation functions

def alloc_interface_buffer(maximus, station, buffer_nb=1):
    buffer = Buffer(type='ETHERNET_TYPE_INTERFACE_BUFFER_ADD', buffer_nb=buffer_nb, maximus=maximus)
    buffer.sendnrecv(maximus, station, count=0) # recv(maximus, count=0) to set creation functions

def realloc_buffer(auto):
    buffer = Buffer('ETHERNET_TYPE_NONE')
    buffer.set_buffer_realloc(auto)

def get_buffer_dict():
    buffer = Buffer('ETHERNET_TYPE_NONE')
    return buffer.get_buffer_dict()