|
I run the Virtualization edition with vtn option with the new OF plugin, and I had VTN Manager install flow entries which had a "Strip VLAN header" action for OpenFlow 1.0 switches.
However, the controller didn't set "Strip VLAN header" action into a flow entry.
When I run the Virtualization edition with the old OF plugin and execute the same scenario, the controller sets "Strip VLAN header" action into a flow entry.
Therefore, there is a bug in the new OF plugin or MD-SAL compatibility bundles.
I think the new OF plugin doesn't correctly handle PopVlanActionCase class (in org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action) when creating flow entries for OpenFlow 1.0.
When VTN Manager tried to install a flow entry which had a "Strip VLAN header" action, MDFlowMapping class (in org.opendaylight.controller.sal.compatibility) converted PopVlan (of org.opendaylight.controller.sal.action.ActionType) to PopVlanActionCase class (of org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase).
FlowProgrammerAdapter class (of org.opendaylight.controller.sal.compatibility) class passed PopVlanActionCase to the new OF plugin.
However, it seemed to me that the new OF plugin ignored PopVlanActionCase for OpenFlow 1.0, although the new OF plugin handle PopVlanActionCase as a "Strip VLAN header" action.
[What I used]
The latest version of the Virtualization Edition on 5th June.
$ pwd
/home/odp/work/integration
odc180 $ git log -3 --oneline
90e2f0c INTEGRAT-4: Remove toaster from virt edition
64e608a Adding extra TCs for RESTCONF
3516960 Uploaded working AD-SAL cluster testcases
[How to produce]
1. Start up the Virtualization edition with of13 and vtn option.
$ ./run.sh -of13 -virt vtn
2. Create a virtual bridge using REST API exposed by VTN Manager.
curl --user "admin":"admin" -H "Accept: application/json" -H \
"Content-type: application/json" -X POST \
http://192.168.60.180:8080/controller/nb/v2/vtn/default/vtns/vtn1 \
-d '
{"description": "Virtual Tenat 1"}
'
curl --user "admin":"admin" -H "Accept: application/json" -H \
"Content-type: application/json" -X POST \
http://192.168.60.180:8080/controller/nb/v2/vtn/default/vtns/vtn1/vbridges/vbr1 \
-d '{}'
curl --user "admin":"admin" -H "Accept: application/json" -H \
"Content-type: application/json" -X POST \
http://192.168.60.180:8080/controller/nb/v2/vtn/default/vtns/vtn1/vbridges/vbr1/interfaces/if1 \
-d '{}'
curl --user "admin":"admin" -H "Accept: application/json" -H \
"Content-type: application/json" -X POST \
http://192.168.60.180:8080/controller/nb/v2/vtn/default/vtns/vtn1/vbridges/vbr1/interfaces/if2 \
-d '{}'
curl --user "admin":"admin" -H "Accept: application/json" -H \
"Content-type: application/json" -X PUT \
http://192.168.60.180:8080/controller/nb/v2/vtn/default/vtns/vtn1/vbridges/vbr1/interfaces/if1/portmap \
-d '{"node":
{"type":"MD_SAL","id":"openflow:3"}
, "port": {"name": "s3-eth1"}}'
curl --user "admin":"admin" -H "Accept: application/json" -H \
"Content-type: application/json" -X PUT \
http://192.168.60.180:8080/controller/nb/v2/vtn/default/vtns/vtn1/vbridges/vbr1/interfaces/if2/portmap \
-d '{"node":
{"type":"MD_SAL","id":"openflow:7"}
, "port": {"name": "s7-eth2"}}'
3. Run Mininet and run OF1.0 switches.
sudo mn --controller=remote,192.168.60.180 --topo tree,3
4. Send ping packets from h1 to h8.
mininet> h1 ping h8
5. Check flow entires in mininet.
Check that "Strip VLAN header" is not set in flow entries, although the first entry on s3 should have a "Strip VLAN header" action.
mininet> dpctl dump-flows
(snip)
-
-
- s3 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=38.36s, table=0, n_packets=0, n_bytes=0, idle_age=38, priority=10,in_port=3,dl_vlan=0,dl_src=12:b9:e4:17:cb:ef,dl_dst=6e:59:89:b8:2a:6e actions=output:1
cookie=0x0, duration=38.317s, table=0, n_packets=0, n_bytes=0, idle_timeout=300, idle_age=38, priority=10,in_port=1,dl_vlan=0,dl_src=6e:59:89:b8:2a:6e,dl_dst=12:b9:e4:17:cb:ef actions=output:3
[The old OF plugin case]
When I run the Virtualization edition with the old OF plugin and executed the same scenario, a flow entry on Mininet was as follows.
The first entry had a "Strip VLAN header" action.
mininet> dpctl dump-flows
(snip)
-
-
- s3 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=26.164s, table=0, n_packets=5, n_bytes=434, idle_age=21, priority=10,in_port=3,vlan_tci=0x0000,dl_src=3e:70:34:62:4c:5d,dl_dst=f6:57:ab:52:db:f2 actions=strip_vlan,output:1
cookie=0x0, duration=26.152s, table=0, n_packets=5, n_bytes=434, idle_timeout=300, idle_age=21, priority=10,in_port=1,vlan_tci=0x0000,dl_src=f6:57:ab:52:db:f2,dl_dst=3e:70:34:62:4c:5d actions=output:3
|
|
Additional information on the new OF plugin on OF 1.0 switches.
---------------------------------------------------------------
To check the behavior of the new OF plugin for PopVlanActionCase class (of org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase), I executed test case f29 of "Test Provider" of OpenFlow Plugin project.
I've found out that when the new OF plugin receives request to create a flow entry which has a "Strip VLAN header" action, it does not send a FLOW_MOD message.
OpenFlow 1.0 has "Strip VLAN header" action, but not "Pop VLAN header".
OpenFlow 1.3 has "Pop VLAN header" action, but not "Strip VLAN header".
So to let MD-SAL abstract this action, I think OF plugin should handle PopVlanActionCase class as "Strip VLAN header" action for OpenFlow 1.0 switches.
[What I used]
The latest code of OpenFlow plugin project on 5th June.
$ git log -3 --oneline
74417f0 BUG-1134: Added TCP flag conversions between md-sal and openflowjava
0326de0 Optimize string splitting by using Splitter class
87fdc8e Improve InjectionKey performance
[How to produce]
1. Build a controller using code of the Git repository of OpenFlow plugin project, and run it.
$ ./run.s
2. Run Mininet and run OF1.0 switches.
sudo mn --controller=remote,192.168.60.180 --topo tree,3
3. Try to install a flow entry.
Execute the following command on OSGi console.
osgi> addMDFlow openflow:1 f29
This command let the new OF plugin install a flow entry which has "Pop VLAN header" action.
See "OpenflowpluginTestCommandProvider.java".
391 case "f29":
392 id += 29;
393 flow.setMatch(createMatch1().build());
394 flow.setInstructions(createAppyActionInstruction21().build());
395 break;
(snip)
1613
1614 private static InstructionsBuilder createAppyActionInstruction21() {
1615
1616 List<Action> actionList = new ArrayList<Action>();
1617 ActionBuilder ab = new ActionBuilder();
1618
1619 PopVlanActionBuilder popVlanActionBuilder = new PopVlanActionBuilder();
1620 ab.setAction(new PopVlanActionCaseBuilder().setPopVlanAction(popVlanActionBuilder.build()).build());
1621 ab.setKey(new ActionKey(0));
1622 actionList.add(ab.build());
1623
1624 // Create an Apply Action
1625 ApplyActionsBuilder aab = new ApplyActionsBuilder();
1626 aab.setAction(actionList);
5. Check flow entires in mininet.
mininet> dpctl dump-flows
-
-
- s1 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
- s2 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
- s3 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
- s4 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
- s5 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
- s6 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
- s7 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
mininet>
|
|
Kamal,
Can you take a look at this one as well on Monday? Hopefully we can have it done on Monday.
Thanks,
Abhijit
|
|
The flow which gets written to the Configuration store in FlowProgrammerAdapter has the correct Actions :
{PopVLan and OutputAction}
. But when the FlowChangeListener gets called after the store change, the PopVLanAction is missing.
FlowProgrammerAdapter.writeFlowAsync()
------------------------------------------------------------
ApplyActions [_action=[
Action [_order=0, _key=ActionKey [_order=0], _action=PopVlanActionCase [augmentation=[]], augmentation=[]],
Action [_order=1, _key=ActionKey [_order=1], _action=OutputActionCase [_outputAction=OutputAction [_outputNodeConnector=Uri [_value=openflow:7:2], augmentation=[]], augmentation=[]], augmentation=[]]], augmentation=[]]
FlowChangeListener.add(), DataObject has the following actions. Note the PopVlanActionCase missing
------------------------------------------------
ApplyActions [_action=[
Action [_order=1, _key=ActionKey [_order=1], _action=OutputActionCase [_outputAction=OutputAction [_outputNodeConnector=Uri [_value=openflow:7:2], augmentation=[]], augmentation=[]], augmentation=[]],
Action [_order=0, _key=ActionKey [_order=0], augmentation=[]]], augmentation=[]]
I am not sure how the actions get serialized/deserialized in the Config store and how the DataObject gets created? Will keep investigating..
|
|
Following gerrits are submitted for review:
Controller: https://git.opendaylight.org/gerrit/#/c/7886/
OFP: https://git.opendaylight.org/gerrit/#/c/7887/
I could see the flows with strip_vlan getting written to the switch
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=0.55s, table=0, n_packets=0, n_bytes=0, idle_timeout=300, idle_age=0, priority=10,in_port=1,vlan_tci=0x0000,dl_src=2a:2f:6a:58:24:2f,dl_dst=f6:86:02:67:c8:b2 actions=output:3
cookie=0x0, duration=0.541s, table=0, n_packets=0, n_bytes=0, idle_age=0, priority=10,in_port=3,vlan_tci=0x0000,dl_src=f6:86:02:67:c8:b2,dl_dst=2a:2f:6a:58:24:2f actions=output:1,strip_vlan
|
|
Hideyuki, could you retest?
|
|
(In reply to Ed Warnicke from comment #5)
> Hideyuki, could you retest?
I'll test it today.
|
|
(In reply to Hideyuki Tai from comment #6)
> (In reply to Ed Warnicke from comment #5)
> > Hideyuki, could you retest?
>
> I'll test it today.
I re-executed the same scenario I written in comment #1.
However, I saw the same issue again.
I captured all packets on OpenFlow channel using tcpdump command, and checked them.
However, all FLOW_MOD messages didn't have a "Strip VLAN header" action.
When I had Mininet send ping packets, I saw many many WARN messages as follows.
I'm not sure if these WARN messages are related to the issue.
2014-06-13 09:46:48.978 EDT [pool-15-thread-2] WARN o.o.y.s.b.g.i.RuntimeGeneratedMappingServiceImpl - Failed to deserialize entry (urn:opendaylight:invento
ry?revision=2013-08-19)nodes/(urn:opendaylight:inventory?revision=2013-08-19)node[
{(urn:opendaylight:inventory?revision=2013-08-19)id=openflow:1}
]/(urn:opend
aylight:flow:inventory?revision=2013-08-19)table[
{(urn:opendaylight:flow:inventory?revision=2013-08-19)id=0}
]/(urn:opendaylight:flow:inventory?revision=2013-
08-19)flow[
{(urn:opendaylight:flow:inventory?revision=2013-08-19)id=9f3a1348-8fdf-465d-a54c-78a820192324}
]/(urn:opendaylight:flow:inventory?revision=2013-08-
19)match/(urn:opendaylight:flow:inventory?revision=2013-08-19)vlan-match
2014-06-13 09:46:48.979 EDT [pool-15-thread-2] WARN o.o.c.m.s.b.i.AbstractForwardedDataBroker - Failed to transform (urn:opendaylight:inventory?revision=201
3-08-19)nodes/(urn:opendaylight:inventory?revision=2013-08-19)node/(urn:opendaylight:inventory?revision=2013-08-19)node[
{(urn:opendaylight:inventory?revision
=2013-08-19)id=openflow:1}
]/AugmentationIdentifier
{childNames=[(urn:opendaylight:flow:inventory?revision=2013-08-19)description, (urn:opendaylight:flow:inven
tory?revision=2013-08-19)group, (urn:opendaylight:flow:inventory?revision=2013-08-19)hardware, (urn:opendaylight:flow:inventory?revision=2013-08-19)manufactu
rer, (urn:opendaylight:flow:inventory?revision=2013-08-19)meter, (urn:opendaylight:flow:inventory?revision=2013-08-19)serial-number, (urn:opendaylight:flow:i
nventory?revision=2013-08-19)software, (urn:opendaylight:flow:inventory?revision=2013-08-19)supported-actions, (urn:opendaylight:flow:inventory?revision=2013
-08-19)supported-instructions, (urn:opendaylight:flow:inventory?revision=2013-08-19)supported-match-types, (urn:opendaylight:flow:inventory?revision=2013-08-
19)switch-features, (urn:opendaylight:flow:inventory?revision=2013-08-19)table]}
/(urn:opendaylight:flow:inventory?revision=2013-08-19)table/(urn:opendaylight
:flow:inventory?revision=2013-08-19)table[
{(urn:opendaylight:flow:inventory?revision=2013-08-19)id=0}
]/(urn:opendaylight:flow:inventory?revision=2013-08-19)f
low/(urn:opendaylight:flow:inventory?revision=2013-08-19)flow[
{(urn:opendaylight:flow:inventory?revision=2013-08-19)id=9f3a1348-8fdf-465d-a54c-78a820192324}
]
/(urn:opendaylight:flow:inventory?revision=2013-08-19)match/(urn:opendaylight:flow:inventory?revision=2013-08-19)vlan-match=ImmutableContainerNode{nodeIdenti
fier=(urn:opendaylight:flow:inventory?revision=2013-08-19)vlan-match, value=[ImmutableContainerNode{nodeIdentifier=(urn:opendaylight:flow:inventory?revision=
2013-08-19)vlan-id, value=[ImmutableLeafNode{nodeIdentifier=(urn:opendaylight:flow:inventory?revision=2013-08-19)vlan-id, value=0, attributes={}}], attribute
s={}}], attributes={}}, omitting it
org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException: Entry deserialization failed
at org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl.fromDataDom(RuntimeGeneratedMappingServiceImpl.java:311) ~[bu
ndlefile:na]
at org.opendaylight.controller.config.yang.md.sal.binding.impl.RuntimeMappingModule$RuntimeGeneratedMappingServiceProxy.fromDataDom(RuntimeMappingModule.
java:151) ~[bundlefile:na]
at org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec.toBindingImpl(BindingToNormalizedNodeCodec.java:202) ~[bundlefile:na]
at org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec.toBinding(BindingToNormalizedNodeCodec.java:132) ~[bundlefile:na]
at org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec.toBinding(BindingToNormalizedNodeCodec.java:258) ~[bundlefile:na]
at org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker.toBinding(AbstractForwardedDataBroker.java:99) ~[bundlefile:na]
at org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker$TranslatedDataChangeEvent.getCreatedData(AbstractForwardedDataBroker.java:
183) [bundlefile:na]
at org.opendaylight.controller.md.sal.binding.impl.LegacyDataChangeEvent$ConfigurationChangeEvent.getCreatedConfigurationData(LegacyDataChangeEvent.java:
163) [bundlefile:na]
at org.opendaylight.controller.frm.AbstractChangeListener.onDataChanged(AbstractChangeListener.java:35) [bundlefile:na]
at org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker$BackwardsCompatibleConfigurationDataChangeInvoker.onDataChanged
(ForwardedBackwardsCompatibleDataBroker.java:458) [bundlefile:na]
at org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker$TranslatingDataChangeInvoker.onDataChanged(AbstractForwardedDataBroker.jav
a:158) [bundlefile:na]
at org.opendaylight.controller.md.sal.dom.store.impl.ChangeListenerNotifyTask.run(ChangeListenerNotifyTask.java:33) [bundlefile:na]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [na:1.7.0_15]
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) [na:1.7.0_15]
at java.util.concurrent.FutureTask.run(FutureTask.java:166) [na:1.7.0_15]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_15]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_15]
at java.lang.Thread.run(Thread.java:722) [na:1.7.0_15]
Caused by: java.lang.IllegalStateException: Failed to lookup instantiated type for path SchemaPath [path=[(urn:opendaylight:inventory?revision=2013-08-19)nod
es, (urn:opendaylight:inventory?revision=2013-08-19)node, (urn:opendaylight:flow:inventory?revision=2013-08-19)table, (urn:opendaylight:flow:inventory?revisi
on=2013-08-19)flow, (urn:opendaylight:flow:inventory?revision=2013-08-19)match], absolute=true]
at com.google.common.base.Preconditions.checkState(Preconditions.java:176) ~[bundlefile:na]
at org.opendaylight.yangtools.sal.binding.generator.impl.LazyGeneratedCodecRegistry.getClassForPath(LazyGeneratedCodecRegistry.java:205) ~[bundlefile:na]
at org.opendaylight.yangtools.sal.binding.generator.impl.InstanceIdentifierCodecImpl.deserializeNodeIdentifier(InstanceIdentifierCodecImpl.java:99) ~[bun
dlefile:na]
at org.opendaylight.yangtools.sal.binding.generator.impl.InstanceIdentifierCodecImpl.deserializePathArgument(InstanceIdentifierCodecImpl.java:219) ~[bund
lefile:na]
at org.opendaylight.yangtools.sal.binding.generator.impl.InstanceIdentifierCodecImpl.deserialize(InstanceIdentifierCodecImpl.java:69) ~[bundlefile:na]
at org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl.fromDataDom(RuntimeGeneratedMappingServiceImpl.java:308) ~[bu
ndlefile:na]
... 17 common frames omitted
[What I used]
I pulled the latest code of Integration Git repository, and built the Virtualization Edition on 13th June.
$ git log -3 --oneline
1bf19ab Merge "Change test case name"
10b7b45 Merge "Introduce the OpenDaylight Toaster Edition"
5ba7a23 Introduce the OpenDaylight Toaster Edition
|
|
I did a git pull on my integration repo.
I am not seeing the patches for 1137 and 1152 in the git log
git log --author="Kamal" does not return anything.
Am i missing something here?
|
|
Kamal,
The integration repo just assembles the various components... I suspect any fixes you did were against the openflowplugin, openflowjava, or controller repos.
So its not at all surprising that there are no commits from you in the integration repo... its just pom files for assembling stuff and test cases.
|
|
The attachment shows the Strip Vlan Action in the flow mod message
|
|
Attachment Screen Shot 2014-06-19 at 3.05.58 PM.png has been added with description: Strip VLan Action in FlowMod
|
|
Hi Hideyuki,
I took the latest of integration and tried the scenario again. I am not able to reproduce the issue you are facing. Please let me know where i might be going wrong.
Here are my complete steps:
1. Took the latest from integration , did a maven clean install.
2. Ran the controller from the integration/vtn distribution
$ ./run.sh -of13 -virt vtn –debug -Xmx2G -XX:MaxPermSize=256M -Dio.netty.leakDetectionLevel=advanced
3. Created the virtual bridge as listed in your 2nd step
4. On mininet VM , ran wireshark and configured it to filter on "of"
5. Ran mininet : sudo mn --controller=remote,192.168.56.1 --topo tree,3
6. Started capturing packets in wireshark
7. Ran h1 ping h8 on mininet. And then later stopped capturing packets in wireshark.
8. the flows in the switch gives the below response,
NOTE: One of the actions have strip_vlan
mininet@mininet-vm:~\> sudo ovs-ofctl dump-flows s3
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=0.088s, table=0, n_packets=0, n_bytes=0, idle_age=0, priority=10,in_port=3,vlan_tci=0x0000,dl_src=26:80:70:be:18:51,dl_dst=6e:0e:5a:e3:7d:53 actions=output:1,strip_vlan
cookie=0x0, duration=0.139s, table=0, n_packets=0, n_bytes=0, idle_timeout=300, idle_age=0, priority=10,in_port=1,vlan_tci=0x0000,dl_src=6e:0e:5a:e3:7d:53,dl_dst=26:80:70:be:18:51 actions=output:3
mininet@mininet-vm:~\> sudo ovs-ofctl dump-flows s7
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=2.727s, table=0, n_packets=3, n_bytes=238, idle_age=0, priority=10,in_port=3,vlan_tci=0x0000,dl_src=6e:0e:5a:e3:7d:53,dl_dst=26:80:70:be:18:51 actions=output:2,strip_vlan
cookie=0x0, duration=2.662s, table=0, n_packets=3, n_bytes=238, idle_timeout=300, idle_age=0, priority=10,in_port=2,vlan_tci=0x0000,dl_src=26:80:70:be:18:51,dl_dst=6e:0e:5a:e3:7d:53 actions=output:3
9. Took a snapshot of the wireshark Flow_Mod. The snapshot shows the Action with "Type: Strip the 802.1q header. (3)". Find the snapshot attached.
Note: All the flow mods DON'T have the strip_vlan action.
Thanks
Kamal
|
|
Hi Hideyuki,
Based on my last update, can you let me know, if it works for you or what i am doing wrong in my testing.
In case it works for you, please mark it resolved.
Thanks
Kamal
|
|
(In reply to Kamal Rameshan from comment #12)
> Hi Hideyuki,
>
> Based on my last update, can you let me know, if it works for you or what i
> am doing wrong in my testing.
>
> In case it works for you, please mark it resolved.
>
> Thanks
> Kamal
Hi Kamal,
Thank you for creating the patch.
I've confirmed that your patch fixes the problem.
I pulled the latest code of Integration Git repository, and built the Virtualization Edition on 23rd June.
Using the Virt Edition, I retested the same scenario I written in comment #1.
On the test, I captured all packets on OpenFlow channels, and I confirmed that the controller correctly "Strip VLAN header" action in FLOW_MOD messages.
A flow table on Mininet has a flow entry which has "Strip VLAN header" action:
mininet> dpctl dump-flows
(snip)
-
-
- s3 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=7.966s, table=0, n_packets=5, n_bytes=434, idle_age=3, priority=10,in_port=3,vlan_tci=0x0000,dl_src=f2:4d:09:09:b0:86,dl_dst=5e:56:cc:04:93:22 actions=output:1,strip_vlan
About Comment 7.
I'm sorry that it seems that I did something wrong in my testing so that I missed Kamal's patches fixed the problem.
|
Generated at Wed Feb 07 20:31:47 UTC 2024 using Jira 8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d.