{"id":4392504,"date":"2022-12-30T09:19:48","date_gmt":"2022-12-30T09:19:48","guid":{"rendered":"https:\/\/www.lastopinion.io\/?p=4392504"},"modified":"2023-01-30T22:01:26","modified_gmt":"2023-01-30T22:01:26","slug":"ecmp-and-load-sharing-on-ip-fragments","status":"publish","type":"post","link":"https:\/\/www.lastopinion.io\/index.php\/2022\/12\/30\/ecmp-and-load-sharing-on-ip-fragments\/","title":{"rendered":"ECMP and Load Sharing on IP Fragments"},"content":{"rendered":"\n<h2 class=\"has-text-color has-medium-font-size wp-block-heading\" style=\"color:#e50055\"><strong>Here is how IP fragmentation works:<\/strong><\/h2>\n\n\n\n<ul class=\"has-black-color has-text-color wp-block-list\">\n<li>A Router receives a large IP packet that exceeds the MTU of its egress interface.<\/li>\n\n\n\n<li>The router divides the packet into smaller fragments, each with a size that is equal to its interfaces MTU egress interface.<\/li>\n\n\n\n<li>The router sets the &#8220;more fragments&#8221; flag in the IP header of all fragments <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\">except <\/mark><\/strong>for the last fragment and sends it over the network.<\/li>\n\n\n\n<li>When the fragments reach their destination, the receiving host reassembles the original packet by concatenating the data payloads of the fragments in the correct order.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">Note: There is often confusion between IP fragmentation and TCP segmentation. It is important to understand the differences between the two:<\/p>\n\n\n\n<ul class=\"has-black-color has-text-color wp-block-list\">\n<li>TCP segmentation involves dividing data into smaller chunks for transmission over a TCP connection.<\/li>\n\n\n\n<li>IP fragmentation occurs at the IP layer and involves breaking up large packets into smaller units that can be transmitted over a network.<\/li>\n\n\n\n<li>IP fragmentation is typically performed by network devices such as routers and firewalls, while TCP segmentation is done by end user devices.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">It is important to note that the<strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\"> TCP or UDP header is only present in the first fragment<\/mark><\/strong>. The following fragments will contain the entire IP header, including the &#8220;fragment offset&#8221; field, which indicates the position of the fragment in the original packet. This information is used by the receiving host or router to reassemble the original packet.<\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">There may be cases where, due to ECMP hashing, the first datagram containing a protocol header is routed to a different device (such as a server or NAT device) for load balancing purposes. This can prevent the reassembly of the fragments and the inability to perform NAT\/Inspection&#8230;<\/p>\n\n\n\n<h2 class=\"has-text-color wp-block-heading\" style=\"color:#e50055\">Now, the interesting part : which path will a fragment follow in a load-balanced network?<\/h2>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">We know that :<\/p>\n\n\n\n<ul class=\"has-black-color has-text-color wp-block-list\">\n<li>Only the first fragment contains the high layer headers (TCP and UDP ports for instance), which can cause problems with IPS, Firewalls, NAT and any statefull devices in the path, but also for reassembly<\/li>\n\n\n\n<li>To avoid polarization (phenomenon of packets being consistently sent over one path in a network, while other paths remain underutilized), we configure the Hashing algorithm to take Layer 4 informations (TCP and UDP ports) into the account <\/li>\n<\/ul>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">Now, imagine we have multiple paths to the same destination, and there is some kind of IPS in the Path. If the IPS doesn&#8217;t see the First Fragment it may drop the packet thinking it is some attack<\/p>\n\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color:#e50055\"><strong>Fragment behaviour on ECMP path on Cisco devices :<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.lastopinion.io\/wp-content\/uploads\/2022\/12\/FramECMP_BGP_Topo.png\" alt=\"\" class=\"wp-image-4392654\" width=\"315\" height=\"339\"\/><\/figure>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">In this first Lab, the CSR1000v router has Load sharing enabled using L4 information<\/p>\n\n\n\n<p class=\"has-text-align-left has-white-color has-black-background-color has-text-color has-background wp-block-paragraph\">Router(config)#ip cef load-sharing algorithm include-ports source destination <\/p>\n\n\n\n<p class=\"has-white-color has-black-background-color has-text-color has-background wp-block-paragraph\">Router#show cef state | i per<br>include-ports source destination per-destination load sharing algorithm, id F6E776D8<\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">ECMP appears to be working as expected based on the CEF viewpoint :<\/p>\n\n\n\n<p class=\"has-white-color has-black-background-color has-text-color has-background wp-block-paragraph\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\">Router#sh ip cef 2.2.2.2<br><\/mark><\/strong>2.2.2.0\/24<br>nexthop 10.1.1.1 GigabitEthernet1<br>nexthop 10.3.3.1 GigabitEthernet2<br><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\">Router#sh ip cef 2.2.2.2 internal<br><\/mark><\/strong>2.2.2.0\/24, epoch 2, flags [rnolbl, rlbls], RIB[B], refcnt 6, per-destination sharing<br>sources: RIB<br>feature space:<br>IPRM: 0x00018000<br>Broker: linked, distributed at 4th priority<br>ifnums:<br>GigabitEthernet1(7): 10.1.1.1<br>GigabitEthernet2(8): 10.3.3.1<br>path list 7FDD622B4BC8, 7 locks, per-destination, flags 0x269 [shble, rif, rcrsv, hwcn, bgp]<br>path 7FDD69B940D8, share 1\/1, type recursive, for IPv4<br>recursive via 10.1.1.1[IPv4:Default], fib 7FDD0112C868, 1 terminal fib, v4:Default:10.1.1.1\/32<br>path list 7FDD622B4DA8, 2 locks, per-destination, flags 0x49 [shble, rif, hwcn]<br>path 7FDD69B94418, share 1\/1, type adjacency prefix, for IPv4<br>attached to GigabitEthernet1, IP adj out of GigabitEthernet1, addr 10.1.1.1 7FDD6A026158<br>path 7FDD69B941A8, share 1\/1, type recursive, for IPv4<br>recursive via 10.3.3.1[IPv4:Default], fib 7FDD0112C968, 1 terminal fib, v4:Default:10.3.3.1\/32<br>path list 7FDD622B4E48, 2 locks, per-destination, flags 0x49 [shble, rif, hwcn]<br>path 7FDD69B944E8, share 1\/1, type adjacency prefix, for IPv4<br>attached to GigabitEthernet2, IP adj out of GigabitEthernet2, addr 10.3.3.1 7FDD6A026370<br>output chain:<br>loadinfo 80007FDCFDF08D68, per-session, 2 choices, flags 0003, 7 locks<br>flags [Per-session, for-rx-IPv4]<br>16 hash buckets<br>&lt; 0 &gt; IP adj out of GigabitEthernet1, addr 10.1.1.1 7FDD6A026158<br>&lt; 1 &gt; IP adj out of GigabitEthernet2, addr 10.3.3.1 7FDD6A026370<br>&lt; 2 &gt; IP adj out of GigabitEthernet1, addr 10.1.1.1 7FDD6A026158<br>&lt; 3 &gt; IP adj out of GigabitEthernet2, addr 10.3.3.1 7FDD6A026370<br>&lt; 4 &gt; IP adj out of GigabitEthernet1, addr 10.1.1.1 7FDD6A026158<br>&lt; 5 &gt; IP adj out of GigabitEthernet2, addr 10.3.3.1 7FDD6A026370<br>&lt; 6 &gt; IP adj out of GigabitEthernet1, addr 10.1.1.1 7FDD6A026158<br>&lt; 7 &gt; IP adj out of GigabitEthernet2, addr 10.3.3.1 7FDD6A026370<br>&lt; 8 &gt; IP adj out of GigabitEthernet1, addr 10.1.1.1 7FDD6A026158<br>&lt; 9 &gt; IP adj out of GigabitEthernet2, addr 10.3.3.1 7FDD6A026370<br>&lt;10 &gt; IP adj out of GigabitEthernet1, addr 10.1.1.1 7FDD6A026158<br>&lt;11 &gt; IP adj out of GigabitEthernet2, addr 10.3.3.1 7FDD6A026370<br>&lt;12 &gt; IP adj out of GigabitEthernet1, addr 10.1.1.1 7FDD6A026158<br>&lt;13 &gt; IP adj out of GigabitEthernet2, addr 10.3.3.1 7FDD6A026370<br>&lt;14 &gt; IP adj out of GigabitEthernet1, addr 10.1.1.1 7FDD6A026158<br>&lt;15 &gt; IP adj out of GigabitEthernet2, addr 10.3.3.1 7FDD6A026370<br>Subblocks:<br>None<\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">In virtual environments, it can be difficult to emulate fragmentation as many virtual devices do not support it. One option is to generate IP fragmentation directly from the Linux testing machine using the &#8220;scapy&#8221; tool.<\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">Using &#8220;scapy&#8221; from the Linux testing machine, we can send two packets that take different paths:<\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">This packet is routed through Router1:<\/p>\n\n\n\n<p class=\"has-white-color has-black-background-color has-text-color has-background wp-block-paragraph\">&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.2&#8243;)\/UDP(sport=7234,dport=<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\"><strong>123<\/strong><\/mark>))<\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">This packet is routed through Router2. The only difference is that the destination port (dport) was changed to &#8216;999&#8217; instead of the previous &#8216;123&#8217;.<\/p>\n\n\n\n<p class=\"has-white-color has-black-background-color has-text-color has-background wp-block-paragraph\">&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.2&#8243;)\/UDP(sport=7234,dport=<strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\">999<\/mark><\/strong>))<\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">Now, let&#8217;s generate the same packet but this time with the &#8220;flags=0x1&#8221; flag added, indicating that the packet is a fragment and that more fragments will follow (MF set).<\/p>\n\n\n\n<p class=\"has-white-color has-black-background-color has-text-color has-background wp-block-paragraph\">&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=999))<br>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=9979))<br>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=4498))<br>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=4489))<br>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=4429))<br>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=4499))<br>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=6799))<br>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=6799))<br>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=6799))<br>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;,dst=&#8221;2.2.2.222&#8243;,flags=0x1)\/UDP(sport=7234,dport=60001))<\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">As a result of adding the &#8220;flags=0x1&#8221; flag, all traffic is now passing through Router1. <\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">No matter what variations were tried, the Cisco algorithm always routed traffic through R1 when the More Fragment Flag was set using &#8220;flags=0x1,&#8221; <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">indicating that the Cisco algorithm will always revert to using L3 functions in this case.<\/mark><\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.lastopinion.io\/wp-content\/uploads\/2022\/12\/2022-12-30-17_06_29-_Standard-input-1.png\" alt=\"\" class=\"wp-image-4392649\" width=\"476\" height=\"352\"\/><figcaption class=\"wp-element-caption\">We can see that all packets are passing through the same router.<\/figcaption><\/figure>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">Now, let&#8217;s try generating the first, middle, and last fragments to ensure that Cisco&#8217;s behavior remains unchanged.<\/p>\n\n\n\n<p class=\"has-white-color has-black-background-color has-text-color has-background wp-block-paragraph\"><strong>First Fragment<br><\/strong>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;, dst=&#8221;2.2.2.222&#8243;, <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\"><strong>flags=0x1, frag=0<\/strong><\/mark>)\/UDP(sport=7234, dport=999))<\/p>\n\n\n\n<p class=\"has-white-color has-black-background-color has-text-color has-background wp-block-paragraph\"><strong>Middle Fragment<br><\/strong>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;, dst=&#8221;2.2.2.222&#8243;, <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\"><strong>flags=0x1, frag=1<\/strong><\/mark>)\/UDP(sport=7234, dport=999))<\/p>\n\n\n\n<p class=\"has-white-color has-black-background-color has-text-color has-background wp-block-paragraph\"><strong>Last Fragment<br><\/strong>&gt; &gt; &gt; send(IP(src=&#8221;1.1.1.1&#8243;, dst=&#8221;2.2.2.222&#8243;, <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\"><strong>flags=0x0, frag=2<\/strong><\/mark>)\/UDP(sport=7234, dport=999))<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.lastopinion.io\/wp-content\/uploads\/2022\/12\/FirstMiddleLastFragScappy.png\" alt=\"\" class=\"wp-image-4392652\" width=\"701\" height=\"242\"\/><\/figure>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">It is interesting that Cisco has taken this into consideration, however, this type of detail is not publicly available and we were unable to find any references on this topic (if you are aware of any, please leave a comment).<\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">You can download the pcap and the lab (eve-ng) here :<\/p>\n\n\n\n<ul class=\"has-black-color has-text-color wp-block-list\">\n<li><a href=\"https:\/\/www.lastopinion.io\/wp-content\/uploads\/2022\/12\/LAB_EVE-NG_EIGBP_LastOpinion.io.zip\" title=\"\">EVE-NG LAB<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.lastopinion.io\/wp-content\/uploads\/2022\/12\/Router1.pcapng\" title=\"\">ROUTER1 PCAP<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.lastopinion.io\/wp-content\/uploads\/2022\/12\/Router2_.pcapng\" title=\"\">ROUTER2 PCAP<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">Note: To view fragments in a Wireshark capture, you need to uncheck the &#8220;reassemble packets&#8221; option.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.lastopinion.io\/wp-content\/uploads\/2022\/12\/2022_12_30_17_13_08_Wireshark_pref.png\" alt=\"\" class=\"wp-image-4392650\" width=\"347\" height=\"198\"\/><\/figure>\n\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color:#e50055\"><strong>Fragment behaviour on L2 and L3 LAG path on Cisco devices :<\/strong><\/p>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\">The same test has been conducted on L2 and L3 LAG ports on Cisco devices, and the same behavior has been observed.<\/p>\n\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color:#e50055\"><strong>In summary :<\/strong><\/p>\n\n\n\n<ul class=\"has-black-color has-text-color wp-block-list\">\n<li>It appears that the Cisco algorithm takes the specific case of &#8220;first fragment&#8221; into consideration and uses <strong>L3<\/strong> hashing computation to avoid related problems. It is not clear if other vendors, such as Arista, Juniper, or Aruba&#8230; have similar behavior. \n<ul class=\"wp-block-list\">\n<li>Please leave a comment on the post if you are aware of any behavior of other vendors.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Fragmentation should be avoided whenever possible, but it may be inevitable in some situations, particularly when using overlay technologies. It is important to carefully plan and test for this behavior and take it into account in the design process when possible.<\/li>\n\n\n\n<li>This test was conducted on Cisco CSR1000v and XRv9K devices and the results were the same.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-black-color has-text-color wp-block-paragraph\"><a href=\"https:\/\/www.linkedin.com\/in\/mehdi-sfar-b4a42910\/\" target=\"_blank\" rel=\"noopener\" title=\"Mehdi SFAR (CCDE 2021:3, CCIE #51583)\">Mehdi SFAR (CCDE 2021:3, CCIE #51583)<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here is how IP fragmentation works: Note: There is often confusion between IP fragmentation and TCP segmentation. It is important to understand the differences between the two: It is important to note that the TCP or UDP header is only present in the first fragment. The following fragments will contain the entire IP header, including [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4392642,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"off","_et_pb_old_content":"<!-- wp:paragraph -->\n<p>First of all, there is so many confusion between IP Fragmentation and TCP Segmentation, that it may be useful to mention the difference :<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>The TCP segmentation process involves dividing the data that needs to be transmitted over a TCP connection into smaller chunks, known as segments. The maximum size of these segments is determined by the MSS, which is based on the MTU of the network interface. The purpose of this segmentation is to ensure that the data can be transmitted efficiently over the network without causing IP fragmentation, which can lead to reduced performance and reliability.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>During the TCP segmentation process, a sequence number is assigned to each segment to help the receiving end reassemble the data in the correct order. This process begins as soon as data is transmitted over a TCP connection, regardless of whether the data is larger than the MSS or not.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>IP fragmentation, on the other hand, is a process that occurs at the IP layer of the OSI model and is not related to TCP. It occurs when an IP packet is too large to be transmitted over a network interface with a smaller MTU. In this case, the packet is divided into smaller fragments, each with its own header and a set of flags to indicate whether it is the first, last, or a middle fragment. The receiving end reassembles the original packet based on these flags and the offset value in the header. IP fragmentation can affect any type of packet, including TCP, UDP, and ICMP packets.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p><\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p><\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p><\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p><\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p><\/p>\n<!-- \/wp:paragraph -->","_et_gb_content_width":"","footnotes":""},"categories":[18],"tags":[16,20,21,17,14],"class_list":["post-4392504","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-ccde","tag-fragmentation","tag-load-sharing","tag-network-architect","tag-network-design"],"_links":{"self":[{"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/posts\/4392504","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/comments?post=4392504"}],"version-history":[{"count":27,"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/posts\/4392504\/revisions"}],"predecessor-version":[{"id":4392861,"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/posts\/4392504\/revisions\/4392861"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/media\/4392642"}],"wp:attachment":[{"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/media?parent=4392504"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/categories?post=4392504"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lastopinion.io\/index.php\/wp-json\/wp\/v2\/tags?post=4392504"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}