1"use strict";(self.webpackChunktigera_docs=self.webpackChunktigera_docs||[]).push([["13790"],{83551:function(i,e,d){d.r(e),d.d(e,{frontMatter:()=>l,default:()=>o,toc:()=>a,metadata:()=>I,assets:()=>t,contentTitle:()=>s});var I=JSON.parse('{"id":"reference/vpp/host-network","title":"Host network configuration","description":"Description of the host network configuration performed by VPP.","source":"@site/calico_versioned_docs/version-3.30/reference/vpp/host-network.mdx","sourceDirName":"reference/vpp","slug":"/reference/vpp/host-network","permalink":"/calico/latest/reference/vpp/host-network","draft":false,"unlisted":false,"editUrl":"https://github.com/tigera/docs/edit/main/calico_versioned_docs/version-3.30/reference/vpp/host-network.mdx","tags":[],"version":"3.30","frontMatter":{"description":"Description of the host network configuration performed by VPP."},"sidebar":"calicoSidebar","previous":{"title":"VPP data plane implementation details","permalink":"/calico/latest/reference/vpp/technical-details"},"next":{"title":"Component versions","permalink":"/calico/latest/reference/component-versions"}}'),c=d(72459),n=d(36870);let l={description:"Description of the host network configuration performed by VPP."},s="Host network configuration",t={},a=[{value:"Big picture",id:"big-picture",level:2},{value:"When VPP starts",id:"when-vpp-starts",level:2},{value:"Packet flow - incoming packet on the uplink",id:"packet-flow---incoming-packet-on-the-uplink",level:2},{value:"Packet flow - pod talking to the api-server",id:"packet-flow---pod-talking-to-the-api-server",level:2}];function Z(i){let e={code:"code",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,n.a)(),...i.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(e.header,{children:(0,c.jsx)(e.h1,{id:"host-network-configuration",children:"Host network configuration"})}),"\n",(0,c.jsx)(e.h2,{id:"big-picture",children:"Big picture"}),"\n",(0,c.jsxs)(e.p,{children:["The VPP-Host connection is a bit particular in the sense that the address of the primary interface is shared by both VPP and Linux.\nLet's say the primary interface (uplink interface on the diagram below) is called ",(0,c.jsx)(e.code,{children:"enp216s0f1"})," and configured with an ",(0,c.jsx)(e.code,{children:"192.168.0.1/24"})," address."]}),"\n",(0,c.jsx)(e.p,{children:"This address must also be the one the api-server will be listening on, as the first address of the uplink (a.k.a main interface for the host)."}),"\n",(0,c.jsx)(e.p,{children:(0,c.jsx)(e.img,{alt:"Network architecture",src:d(43337).Z+"",width:"394",height:"323"})}),"\n",(0,c.jsx)(e.h2,{id:"when-vpp-starts",children:"When VPP starts"}),"\n",(0,c.jsxs)(e.ul,{children:["\n",(0,c.jsxs)(e.li,{children:["\n",(0,c.jsx)(e.p,{children:"It grabs the primary interface with the chosen driver, either placing it in a dedicated network namespace, or removing it entirely as a Linux netdev depending on the driver. In any case, the interface disappears from the host's root network namespace."}),"\n"]}),"\n",(0,c.jsxs)(e.li,{children:["\n",(0,c.jsxs)(e.p,{children:["It configures it in VPP with the same configuration (addresses, routes) it had in Linux. So issuing ",(0,c.jsx)(e.code,{children:"show int addr"})," in VPP will give something like"]}),"\n",(0,c.jsx)(e.pre,{children:(0,c.jsx)(e.code,{children:"vpp# sh int addr\navf-0/d8/a/0 (up):\n L3 192.168.0.1/24\n"})}),"\n"]}),"\n",(0,c.jsxs)(e.li,{children:["\n",(0,c.jsxs)(e.p,{children:["It creates a ",(0,c.jsx)(e.code,{children:"tap"})," interface between VPP and the host"]}),"\n"]}),"\n",(0,c.jsxs)(e.li,{children:["\n",(0,c.jsx)(e.p,{children:"This tap interface is given the same name and MAC address as the original interface in the host's root network namespace"}),"\n"]}),"\n",(0,c.jsxs)(e.li,{children:["\n",(0,c.jsx)(e.p,{children:"This interface is also reconfigured with all the addresses and routes that the host had configured on the original interface"}),"\n",(0,c.jsx)(e.pre,{children:(0,c.jsx)(e.code,{className:"language-bash",children:"ip addr show enp216s0f1\n3: enp216s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000\n link/ether 52:54:00:40:46:8e brd ff:ff:ff:ff:ff:ff\n inet 192.168.0.1/24 brd 192.168.0.255 scope global eth1\n valid_lft forever preferred_lft forever\n\nip route\ndefault via 192.168.0.254 dev enp216s0f1 proto dhcp src 192.168.0.1 metric 100\n${SERVICE_CIDR} via 192.168.0.254 dev enp216s0f1 proto static mtu 1440\n${POD_CIDR} via 192.168.0.254 dev enp216s0f1 proto static mtu 1440\n192.168.0.0/24 dev enp216s0f1 proto kernel scope link src 192.168.0.254\n"})}),"\n",(0,c.jsxs)(e.p,{children:["The new ",(0,c.jsx)(e.code,{children:"tap"})," interface (named ",(0,c.jsx)(e.code,{children:"enp216s0f1"})," in this example) is also configured with routes towards the Kubernetes service CIDR and the pod CIDR, so that the Linux host can reach the workloads through VPP. These routes use a reduced MTU to accommodate for encapsulations."]}),"\n"]}),"\n",(0,c.jsxs)(e.li,{children:["\n",(0,c.jsxs)(e.p,{children:["In VPP you will find it with the name ",(0,c.jsx)(e.code,{children:"tap0"}),". It is configured unnumbered, as a child of the primary interface ",(0,c.jsx)(e.code,{children:"avf-0/d8/a/0"}),"."]}),"\n",(0,c.jsx)(e.pre,{children:(0,c.jsx)(e.code,{children:"vpp# sh int addr\ntun0 (up):\n unnumbered, use avf-0/d8/a/0\n L3 192.168.0.1/24\n"})}),"\n"]}),"\n",(0,c.jsxs)(e.li,{children:["\n",(0,c.jsx)(e.p,{children:"It is also registered as the default punt path. This means that all the traffic that would be dropped by VPP (which includes the traffic to the VPP address that is not handled by VPP itself, but not the tunnel traffic which is decapsulated/decrypted by VPP) will be passed to this interface, so the Linux host will receive and process it."}),"\n",(0,c.jsx)(e.pre,{children:(0,c.jsx)(e.code,{children:"vpp# sh ip punt redirect\n rx local0 via:\n path-list:[31] locks:1 flags:no-uRPF, uPRF-list:24 len:1 itfs:[2, ]\n path:[41] pl-index:31 ip4 weight=1 pref=0 attached-nexthop: oper-flags:resolved,\n 169.254.0.1 tap0\n [@0]: ipv4 via 169.254.0.1 tap0: mtu:1500 next:6 flags:[features ] 52540040468e
102ca11c0fd100800\n forwarding\n [@1]: ipv4 via 169.254.0.1 tap0: mtu:1500 next:6 flags:[features ] 52540040468e02ca11c0fd100800\n"})}),"\n",(0,c.jsx)(e.p,{children:"For the v6 configuration:"}),"\n",(0,c.jsx)(e.pre,{children:(0,c.jsx)(e.code,{children:"vpp# sh ip6 punt redirect\n"})}),"\n"]}),"\n"]}),"\n",(0,c.jsx)(e.h2,{id:"packet-flow---incoming-packet-on-the-uplink",children:"Packet flow - incoming packet on the uplink"}),"\n",(0,c.jsxs)(e.p,{children:["A packet destined to the host arrives on the uplink, let's say it has ",(0,c.jsx)(e.code,{children:"src=192.168.0.2,dst=192.168.0.1"})]}),"\n",(0,c.jsxs)(e.ul,{children:["\n",(0,c.jsx)(e.li,{children:"VPP receives it, sees that the destination address is the one configured on its interface"}),"\n",(0,c.jsxs)(e.li,{children:["As it doesn't have specific handling configured for this packet, it looks up the punt path, and sends it into ",(0,c.jsx)(e.code,{children:"tap0"})]}),"\n",(0,c.jsxs)(e.li,{children:["Linux receives it on the tap interface which is configured with ",(0,c.jsx)(e.code,{children:"192.168.0.1/32"})," and so processes it normally"]}),"\n"]}),"\n",(0,c.jsxs)(e.p,{children:["The reply is now emitted by the host with ",(0,c.jsx)(e.code,{children:"src=192.168.0.1,dst=192.168.0.2"})]}),"\n",(0,c.jsxs)(e.ul,{children:["\n",(0,c.jsxs)(e.li,{children:["Linux looks up the route for ",(0,c.jsx)(e.code,{children:"192.168.0.0/24"}),", forwards it into the tap interface"]}),"\n",(0,c.jsxs)(e.li,{children:["VPP receives it on the interface ",(0,c.jsx)(e.code,{children:"tap0"})]}),"\n",(0,c.jsxs)(e.li,{children:["It looks up ",(0,c.jsx)(e.code,{children:"192.168.0.2"})," in the fib, finds a route on the uplink interface (configured with ",(0,c.jsx)(e.code,{children:"192.168.0.1/24"}),")"]}),"\n",(0,c.jsx)(e.li,{children:"The packet is sent on the uplink"}),"\n"]}),"\n",(0,c.jsx)(e.h2,{id:"packet-flow---pod-talking-to-the-api-server",children:"Packet flow - pod talking to the api-server"}),"\n",(0,c.jsxs)(e.p,{children:["Let's say the api server lives on ",(0,c.jsx)(e.code,{children:"Node A"}),"."]}),"\n",(0,c.jsxs)(e.p,{children:["If a pod on ",(0,c.jsx)(e.code,{children:"Node B"})," wants to talk to the api-server on ",(0,c.jsx)(e.code,{children:"Node A"}),", the packet flow will be the same as described above."]}),"\n",(0,c.jsxs)(e.ul,{children:["\n",(0,c.jsxs)(e.li,{children:["In ",(0,c.jsx)(e.code,{children:"Node B"}),", standard routing happens (",(0,c.jsx)(e.code,{children:"sh ip fib <someip>"})," will give details on this node)"]}),"\n",(0,c.jsxs)(e.li,{children:["When reaching ",(0,c.jsx)(e.code,{children:"Node A"}),", we're in the same situation as previously"]}),"\n"]}),"\n",(0,c.jsxs)(e.p,{children:["If a pod on ",(0,c.jsx)(e.code,{children:"Node A"})," wants to talk to the api-server on ",(0,c.jsx)(e.code,{children:"Node A"}),", let's say the packet is ",(0,c.jsx)(e.code,{children:"src=10.0.0.1,dst=192.168.0.1"})," with ",(0,c.jsx)(e.code,{children:"10.0.0.1"})," being the pod address, then:"]}),"\n",(0,c.jsxs)(e.ul,{children:["\n",(0,c.jsx)(e.li,{children:"Things happen exactly the same way as if the packet was coming from the uplink"}),"\n",(0,c.jsxs)(e.li,{children:["This time packets come into vpp through ",(0,c.jsx)(e.code,{children:"tunN"})," corresponding to the pod interface, and is then punted to ",(0,c.jsx)(e.code,{children:"tap0"})," towards the host"]}),"\n",(0,c.jsxs)(e.li,{children:["The return traffic from the host is received by VPP on ",(0,c.jsx)(e.code,{children:"tap0"}),", and is routed directly to the pod on ",(0,c.jsx)(e.code,{children:"tunN"})]}),"\n"]})]})}function o(i={}){let{wrapper:e}={...(0,n.a)(),...i.components};return e?(0,c.jsx)(e,{...i,children:(0,c.jsx)(Z,{...i})}):Z(i)}},43337:function(i,e,d){d.d(e,{Z:()=>I});let I="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzk0cHgiIGhlaWdodD0iMzIzcHgiIHZpZXdCb3g9Ii0wLjUgLTAuNSAzOTQgMzIzIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiByZ2IoMjU1LCAyNTUsIDI1NSk7Ij48ZGVmcy8+PGc+PHJlY3QgeD0iMjIiIHk9IjIyIiB3aWR0aD0iMTgwIiBoZWlnaHQ9IjEwMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDE3OHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDcycHg7IG1hcmdpbi1sZWZ0OiAyM3B4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj48Zm9udCBzdHlsZT0iZm9udC1zaXplOiAxOHB4Ij5Ib3N0PC9mb250PjxiciAvPjxiciAvPjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxMTIiIHk9Ijc2IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkhvc3QuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjI4MiIgeT0iNDIiIHdpZHRoPSI5MCIgaGVpZ2h0PSI4MCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMDA3MGMwIiBzdHJva2Utd2lkdGg9IjQiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48cmVjdCB4PSIyMiIgeT0iMTYyIiB3aWR0aD0iMzUwIiBoZWlnaHQ9IjgwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlYTIwMmMiIHN0cm9rZS13aWR0aD0iNCIgcG9pbnRlci1ldmVud
1HM9ImFsbCIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAzNDhweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAyMDJweDsgbWFyZ2luLWxlZnQ6IDIzcHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGNlbnRlcjsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6IEhlbHZldGljYTsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IHdvcmQtd3JhcDogbm9ybWFsOyAiPjxmb250IHN0eWxlPSJmb250LXNpemU6IDE4cHgiPlZQUDxiciAvPjxiciAvPjwvZm9udD48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk3IiB5PSIyMDYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+VlBQLi4uPC90ZXh0Pjwvc3dpdGNoPjwvZz48cmVjdCB4PSIyNjIiIHk9IjMyIiB3aWR0aD0iOTAiIGhlaWdodD0iODAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzAwNzBjMCIgc3Ryb2tlLXdpZHRoPSI0IiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PHJlY3QgeD0iMjQyIiB5PSIyMiIgd2lkdGg9IjkwIiBoZWlnaHQ9IjgwIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMwMDcwYzAiIHN0cm9rZS13aWR0aD0iNCIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA4OHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDYycHg7IG1hcmdpbi1sZWZ0OiAyNDNweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogY2VudGVyOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogSGVsdmV0aWNhOyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+PGZvbnQ+PGZvbnQgc3R5bGU9ImZvbnQtc2l6ZTogMThweCI+UG9kczwvZm9udD48YnIgLz48L2ZvbnQ+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjI4NyIgeT0iNjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+UG9kcyYjeGE7PC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDMyNS42MSAxMjUuNzUgTCAzMTMuNTQgMTU4LjI1IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9InN0cm9rZSIvPjxlbGxpcHNlIGN4PSIzMjciIGN5PSIxMjIiIHJ4PSI0IiByeT0iNCIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PGVsbGlwc2UgY3g9IjMxMi4xNSIgY3k9IjE2MiIgcng9IjQiIHJ5PSI0IiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48cGF0aCBkPSJNIDMwNS42NSAxMTUuNzYgTCAyOTAuNCAxNTguMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ic3Ryb2tlIi8+PGVsbGlwc2UgY3g9IjMwNyIgY3k9IjExMiIgcng9IjQiIHJ5PSI0IiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48ZWxsaXBzZSBjeD0iMjg5LjA1IiBjeT0iMTYyIiByeD0iNCIgcnk9IjQiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxwYXRoIGQ9Ik0gMjg1LjY5IDEwNS43OCBMIDI2Ny42MSAxNTcuODIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ic3Ryb2tlIi8+PGVsbGlwc2UgY3g9IjI4NyIgY3k9IjEwMiIgcng9IjQiIHJ5PSI0IiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48ZWxsaXBzZSBjeD0iMjY2LjMiIGN5PSIxNjEuNiIgcng9IjQiIHJ5PSI0IiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48cGF0aCBkPSJNIDE5Ni43OCAyNDYgTCAxOTcgMjkyIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9InN0cm9rZSIvPjxlbGxpcHNlIGN4PSIxOTYuNzYiIGN5PSIyNDIiIHJ4PSI0IiByeT0iNCIgZmlsbD0iIzAw
1MDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PHJlY3QgeD0iMjAyIiB5PSIyNjIiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMjcycHg7IG1hcmdpbi1sZWZ0OiAyNTJweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogY2VudGVyOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogSGVsdmV0aWNhOyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsgIj51cGxpbmsgaW50ZXJmYWNlPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjI1MiIgeT0iMjc2IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPnVwbGluayBpbnRlcmZhY2U8L3RleHQ+PC9zd2l0Y2g+PC9nPjxyZWN0IHg9IjkyIiB5PSIxNjciIHdpZHRoPSI0MCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxNzdweDsgbWFyZ2luLWxlZnQ6IDExMnB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm93cmFwOyAiPnR1bjA8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTEyIiB5PSIxODEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+dHVuMDwvdGV4dD48L3N3aXRjaD48L2c+PHBhdGggZD0iTSAxMTEuNzQgMTI2IEwgMTExLjYyIDE1Ny45MiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJzdHJva2UiLz48ZWxsaXBzZSBjeD0iMTExLjc2IiBjeT0iMTIyIiByeD0iNCIgcnk9IjQiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxlbGxpcHNlIGN4PSIxMTEuNiIgY3k9IjE2MS45MiIgcng9IjQiIHJ5PSI0IiBmaWxsPSIjMDAwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48cmVjdCB4PSIzNyIgeT0iOTciIHdpZHRoPSIxNTAiIGhlaWdodD0iMjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTA3cHg7IG1hcmdpbi1sZWZ0OiAxMTJweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogY2VudGVyOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogSGVsdmV0aWNhOyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsgIj48c3Bhbj52cHB0YXAwIC0gMTkyLjE2OC4wLjEvMzI8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjExMiIgeT0iMTExIiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPnZwcHRhcDAgLSAxOTIuMTY4LjAuMS8zMjwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMjY3IiB5PSIxNjciIHdpZHRoPSI1MCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxNzdweDsgbWFy
1Z2luLWxlZnQ6IDI5MnB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm93cmFwOyAiPnR1bjEuLk48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMjkyIiB5PSIxODEiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+dHVuMS4uTjwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTQ3IiB5PSIyMDciIHdpZHRoPSIxMDAiIGhlaWdodD0iMzAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMjIycHg7IG1hcmdpbi1sZWZ0OiAxOTdweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogY2VudGVyOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogSGVsdmV0aWNhOyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vd3JhcDsgIj5lbnAyMTZzMGYxPGJyIC8+MTkyLjE2OC4wLjEvMjQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMTk3IiB5PSIyMjYiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+ZW5wMjE2czBmMS4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vZGVzay5kcmF3LmlvL3N1cHBvcnQvc29sdXRpb25zL2FydGljbGVzLzE2MDAwMDQyNDg3IiB0YXJnZXQ9Il9ibGFuayI+PHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMHB4IiB4PSI1MCUiIHk9IjEwMCUiPlZpZXdlciBkb2VzIG5vdCBzdXBwb3J0IGZ1bGwgU1ZHIDEuMTwvdGV4dD48L2E+PC9zd2l0Y2g+PC9zdmc+"},36870:function(i,e,d){d.d(e,{Z:()=>s,a:()=>l});var I=d(84449);let c={},n=I.createContext(c);function l(i){let e=I.useContext(n);return I.useMemo(function(){return"function"==typeof i?i(e):{...e,...i}},[e,i])}function s(i){let e;return e=i.disableParentContext?"function"==typeof i.components?i.components(c):i.components||c:l(i.components),I.createElement(n.Provider,{value:e},i.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.