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