new E2AP and E2SMKPM files
[o-du/l2.git] / src / codec_utils / e2ap.lua
1 ----------------------------------------
2 -- script-name: e2ap.lua
3 ----------------------------------------
4
5 ----------------------------------------
6 -- creates a Proto object, but doesn't register it yet
7 local E2AP = Proto("E2AP","E2 Application Protocol")
8
9 ----------------------------------------                
10 local E2apPduEnum = {
11                 [0] = "initiatingMessage",
12                 [1] = "successfulOutcome",
13                 [2] = "unsuccessfulOutcome" }
14         
15 local ProcedureCodeE2 = {
16                 [1] = "ProcedureCodeE2_id_E2setup",
17                 [2] = "ProcedureCodeE2_id_ErrorIndicationE2",
18                 [3] = "ProcedureCodeE2_id_Reset",
19                 [4] = "ProcedureCodeE2_id_RICcontrol",
20                 [5] = "ProcedureCodeE2_id_RICindication",
21                 [6] = "ProcedureCodeE2_id_RICserviceQuery",
22                 [7] = "ProcedureCodeE2_id_RICserviceUpdate",
23                 [8] = "ProcedureCodeE2_id_RICsubscription",
24                 [9] = "ProcedureCodeE2_id_RICsubscriptionDelete" }
25
26 local CriticalityE2 ={
27                 [0] = "CriticalityE2_reject",
28                 [1] = "CriticalityE2_ignore",
29                 [2] = "CriticalityE2_notify" }
30                 
31 local InitiatingMessageE2ValuePrEnum = {
32                 [0] = "InitiatingMessageE2__value_PR_NOTHING",
33                 [1] = "InitiatingMessageE2__value_PR_RICsubscriptionRequest",
34                 [2] = "InitiatingMessageE2__value_PR_RICsubscriptionDeleteRequest",
35                 [3] = "InitiatingMessageE2__value_PR_RICserviceUpdate",
36                 [4] = "InitiatingMessageE2__value_PR_RICcontrolRequest",
37                 [5] = "InitiatingMessageE2__value_PR_E2setupRequest",
38                 [6] = "InitiatingMessageE2__value_PR_ResetRequest",
39                 [7] = "InitiatingMessageE2__value_PR_RICindication",
40                 [8] = "InitiatingMessageE2__value_PR_RICserviceQuery",
41                 [9] = "InitiatingMessageE2__value_PR_ErrorIndicationE2" }
42
43 local E2PotocolIEs = {
44         [1] = "id_CauseE2",
45         [2] = "id_CriticalityDiagnosticsE2",
46         [3] = "id_GlobalE2node_ID",
47         [4] = "id_GlobalRIC_ID",
48         [5] = "id_RANfunctionID",
49         [6] = "id_RANfunctionID_Item",
50         [7] = "id_RANfunctionIEcause_Item",
51         [8] = "id_RANfunction_Item",
52         [9] = "id_RANfunctionsAccepted",
53         [10] = "id_RANfunctionsAdded",
54         [11] = "id_RANfunctionsDeleted",
55         [12] = "id_RANfunctionsModified",
56         [13] = "id_RANfunctionsRejected",
57         [14] = "id_RICaction_Admitted_Item",
58         [15] = "id_RICactionID",
59         [16] = "id_RICaction_NotAdmitted_Item",
60         [17] = "id_RICactions_Admitted",
61         [18] = "id_RICactions_NotAdmitted",
62         [19] = "id_RICaction_ToBeSetup_Item",
63         [20] = "id_RICcallProcessID",
64         [21] = "id_RICcontrolAckRequest",
65         [22] = "id_RICcontrolHeader",
66         [23] = "id_RICcontrolMessage",
67         [24] = "id_RICcontrolStatus",
68         [25] = "id_RICindicationHeader",
69         [26] = "id_RICindicationMessage",
70         [27] = "id_RICindicationSN",
71         [28] = "id_RICindicationType",
72         [29] = "id_RICrequestID",
73         [30] = "id_RICsubscriptionDetails",
74         [31] = "id_TimeToWaitE2",
75         [32] = "id_RICcontrolOutcome"
76 }
77
78         
79 --payload fields start
80 local RIC_indication = "Ric Indication Message"
81
82 local Initiating_Message_Type_Value = {
83         value = "value"--, nil,InitiatingMessageE2ValuePrEnum, 0xFF)
84 }
85
86 local InitiatingMessageE2 = {
87         Initiating_Message_E2 = "Initiating Message E2",
88         procedureCode = "ProcedureCode: ",
89         criticality   = "Criticality: "
90 }
91         --value       = ProtoField.uint16("Initiating_Message_Type_Value.value", "value")
92
93 local InitiatingMessageE2__value_u = {
94 RICsubscriptionRequest           = "RIC subscription Request",
95 RICsubscriptionDeleteRequest = "RIC subscription Delete Request",
96 RICserviceUpdate                         = "RIC service Update",
97 RICcontrolRequest                        = "RIC control Request",
98 E2setupRequest                           = "E2 setup Request",
99 ResetRequest                             = "Reset Request",
100 RICindication                            = "RIC indication",
101 RICserviceQuery                          = "RIC service Query",
102 ErrorIndicationE2                        = "Error Indication E2"
103 }
104
105 local successfulOutcomeE2 = {
106         successOutcomeMsg = "successfulOutcome",
107         procedureCode = "procedureCode: ",
108         criticality = "criticality: ",
109         valueLen = "Value Length: ",
110         value = "Value"
111 }
112
113 local e2SetupResponse = "E2SetupResponse"
114 local protocolIE = "protocolIEs: "
115 local protocolItem = "Item "
116 local protocolIEField = {
117         protocolIEFieldMsg = "ProtocolIE-Field",
118         id = "id: ",
119         criticality = "criticality: ",
120         valueLen = "Value Length: ",
121         value = "Value"
122 }
123
124 E2AP.fields = {
125         --successfulOutcomeE2.procedureCode
126 }
127
128 function fetch2Bytes(tvbuf, offset)
129         local fbyte = tvbuf:range(offset, 1):le_uint()
130         local fbyte1 = bit.lshift(fbyte, 8)
131         local sbyte = tvbuf:range(offset + 1, 1):le_uint()
132         local result = bit.bor(fbyte1, sbyte)
133         return result
134 end
135 function addE2apInitiatingMessageToTree(tvbuf, tree, offset, endianness)
136
137         local info = tvbuf:range(offset, 1)
138         local initiatingMessageE2Tree = tree:add(info, InitiatingMessageE2.Initiating_Message_E2)
139
140         local procId = tvbuf:range(offset,1):le_uint()
141         strId = tostring(ProcedureCodeE2[procId]) .. " (" .. tostring(procId) ..")"
142         tree:add(tvbuf:range(offset,1), InitiatingMessageE2.procedureCode .. strId)
143         offset = offset + 1
144
145         local criticalityId = tvbuf:range(offset,1):le_uint()
146         strId = tostring(CriticalityE2[criticalityId]) .. " (" .. tostring(criticalityId) ..")"
147         tree:add(tvbuf:range(offset,1), InitiatingMessageE2.criticality .. strId)
148         offset = offset + 1
149
150         -- value cfg
151         --local valueinitiatingMessageType = initiatingMessageE2Tree:add(tvbuf:range(offset,offset),Initiating_Message_E2.value)
152
153 end
154
155 function addGobalRICIdToTree(tvbuf, valueTree, offset, valueLen, endianness)
156 end
157
158 function addE2SetupResponseToTree(tvbuf, valueTree, offset, pktlen, endianness)
159         local e2SetupResponseTree = valueTree:add(tvbuf:range(offset, pktlen), e2SetupResponse)
160                         
161                 local extBit = tvbuf:range(offset,1):le_uint()
162                 if(extBit == 0) then
163                         e2SetupResponseTree:add(tvbuf:range(offset,1), "<" .. extBit .. "... .... Extension Bit: FALSE>")
164                 else
165                         e2SetupResponseTree:add(tvbuf:range(offset,1), "<" .. extBit .. "... .... Extension Bit: TRUE>")
166                 end
167                 offset = offset + 1
168                 
169                 local seqLen = fetch2Bytes(tvbuf, offset)
170                 e2SetupResponseTree:add(tvbuf:range(offset, 2), "<Sequence-Of Length: " .. seqLen .. ">")
171                 local protoIeTree = e2SetupResponseTree:add(tvbuf:range(offset, 2), protocolIE .. seqLen .. " items")
172                 offset = offset + 2
173                         
174                 for ie=0, seqLen-1, 1
175                 do
176                     local protocolIEId = fetch2Bytes(tvbuf, offset)
177                         strId = tostring(E2PotocolIEs[protocolIEId])
178                         local itemTree = protoIeTree:add(protocolItem .. ie .. ": " .. strId)
179                         
180                         strId = strId .. " (" .. tostring(protocolIEId) ..")"
181                         local protocolFieldTree = itemTree:add(tvbuf:range(offset,2), protocolIEField.protocolIEFieldMsg)
182                                 protocolFieldTree:add(protocolIEField.id .. strId)
183                                 offset = offset + 2
184                                         
185                                 local criticalityId = tvbuf:range(offset,1):le_uint()
186                                 protocolFieldTree:add(tvbuf:range(offset,1), "<Enumerated Index: " .. criticalityId ..">")
187                                 strId = tostring(CriticalityE2[criticalityId]) .. " (" .. tostring(criticalityId) ..")"
188                                 protocolFieldTree:add(tvbuf:range(offset,1), protocolIEField.criticality .. strId)
189                                 offset = offset + 1
190                                 
191                                 local valueLen = tvbuf:range(offset,1):le_uint()
192                                 protocolFieldTree:add(tvbuf:range(offset,1), "<" .. protocolIEField.valueLen .. valueLen ..">")
193                                 offset = offset + 1
194                                 
195                                 local valueTree = protocolFieldTree:add(tvbuf:range(offset, valueLen), protocolIEField.value)
196                                 
197                                 if(protocolIEId == 4) then
198                                         addGobalRICIdToTree(tvbuf, valueTree, offset, valueLen, endianness)
199                                 end
200                 end
201 end
202
203 function addE2apSuccessfulOutcomeToTree(tvbuf, tree, offset, pktlen, endianness)
204         local successfulOutcomeTree = tree:add(tvbuf:range(offset, (pktlen-offset)), successfulOutcomeE2.successOutcomeMsg)
205                 local procId = tvbuf:range(offset,1):le_uint()
206                 strId = tostring(ProcedureCodeE2[procId]) .. " (" .. tostring(procId) ..")"
207                 successfulOutcomeTree:add(tvbuf:range(offset,1), successfulOutcomeE2.procedureCode .. strId)
208                 offset = offset + 1
209                 
210                 local criticalityId = tvbuf:range(offset,1):le_uint()
211                 successfulOutcomeTree:add(tvbuf:range(offset,1), "<Enumerated Index: " .. criticalityId ..">")
212         strId = tostring(CriticalityE2[criticalityId]) .. " (" .. tostring(criticalityId) ..")"
213         successfulOutcomeTree:add(tvbuf:range(offset,1), successfulOutcomeE2.criticality .. strId)
214         offset = offset + 1
215                 
216                 local valueLen = tvbuf:range(offset,1):le_uint()
217                 successfulOutcomeTree:add(tvbuf:range(offset,1), "<" .. successfulOutcomeE2.valueLen .. valueLen ..">")
218                 offset = offset + 1
219                 
220                 local valueTree = successfulOutcomeTree:add(tvbuf:range(offset, valueLen), successfulOutcomeE2.value)
221                 
222                 if(procId == 1) then
223                         addE2SetupResponseToTree(tvbuf, valueTree, offset, valueLen, endianness)
224                 end
225 end
226 ----------------------------------------
227 -- The following creates the callback function for the dissector.
228 -- The 'tvbuf' is a Tvb object, 'pktinfo' is a Pinfo object, and 'root' is a TreeItem object.
229 -- Whenever Wireshark dissects a packet that our Protocol is hooked into, it will call
230 -- this function and pass it these arguments for the packet it's dissecting.
231 function E2AP.dissector(tvbuf,pktinfo,root)
232
233     -- set the protocol column to show our protocol name
234     pktinfo.cols.protocol:set("E2AP")
235
236     -- We want to check that the packet size is rational during dissection, so let's get the length of the
237     -- packet buffer (Tvb).
238     local pktlen = tvbuf:reported_length_remaining()
239
240     -- We start by adding our protocol to the dissection display tree.
241     -- A call to tree:add_packet_field() returns the child created, so we can add more "under" it using that return value.
242     -- The second argument is how much of the buffer/packet this added tree item covers/represents
243     local offset = 0
244     stream = " "
245     local endianness = string.byte(string.dump(function() end), 7)
246     local tree = root:add(E2AP, tvbuf:range(offset,pktlen))
247
248        
249     -- Now let's add our protocol header fields under the protocol tree we just created.
250
251     local fByte = tvbuf:range(offset,1):le_uint()
252         local apiId = bit.rshift(fByte, 5)
253         tree:add(tvbuf:range(offset,1), "<Choice Index: " .. apiId ..">")
254     strId = tostring(E2apPduEnum[apiId]) .. " (" .. tostring(apiId) ..")"
255     tree:add(tvbuf:range(offset,1), "E2AP-PDU: " .. strId)
256         offset = offset + 1
257
258     -- Now let's add our protocol fields under the protocol tree we just created.
259         if (apiId == 0) then
260                 addE2apInitiatingMessageToTree(tvbuf, tree, offset, endianness)
261         end
262         if(apiId == 1) then
263                 addE2apSuccessfulOutcomeToTree(tvbuf, tree, offset, pktlen, endianness)
264         end
265         
266 end -- end of dissector funciton
267
268         ----------------------------------------
269         -- we want to have our protocol dissection invoked for a specific UDP port,
270         -- so get the udp dissector table and add our protocol to it
271         DissectorTable.get("sctp.port"):add(36421, E2AP)
272         -- our protocol (Proto) gets automatically registered after this script finishes loading
273         ----------------------------------------
274