αž™αžΎαž„αžŸαžšαžŸαŸαžšαž€αžΆαžšαž€αžΆαžšαž–αžΆαžšαž”αŸ’αžšαž†αžΆαŸ†αž„αž“αžΉαž„αž€αžΆαžšαžœαžΆαž™αž”αŸ’αžšαž αžΆαžš DDoS αž›αžΎ XDP αŸ” αž•αŸ’αž“αŸ‚αž€αž“αž»αž™αž€αŸ’αž›αŸαž’αŸŠαŸ‚αžš

αž”αž…αŸ’αž…αŸαž€αžœαž·αž‘αŸ’αž™αžΆ eXpress Data Path (XDP) αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž…αžšαžΆαž…αžšαž…αŸƒαžŠαž“αŸ’αž™αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαž“αŸ…αž›αžΎαž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž›αžΈαž“αž»αž… αž˜αž»αž“αž–αŸαž›αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž…αžΌαž›αž‘αŸ…αž€αŸ’αž“αž»αž„αž‡αž„αŸ‹αž”αžŽαŸ’αžαžΆαž‰αžαžΊαžŽαŸ‚αž›αŸ” αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ XDP - αž€αžΆαžšαž€αžΆαžšαž–αžΆαžšαž”αŸ’αžšαž†αžΆαŸ†αž„αž“αžΉαž„αž€αžΆαžšαžœαžΆαž™αž”αŸ’αžšαž αžΆαžš DDoS (CloudFlare) αžαž˜αŸ’αžšαž„αžŸαŸ’αž˜αž»αž‚αžŸαŸ’αž˜αžΆαž‰ αž€αžΆαžšαž”αŸ’αžšαž˜αžΌαž›αžŸαŸ’αžαž·αžαž· (Netflix) αŸ” αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ XDP αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αžŠαŸ„αž™αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αž·αž˜αŸ’αž˜αž·αž eBPF αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž–αž½αž€αž‚αŸαž˜αžΆαž“αž€αžΆαžšαžšαžΉαžαž”αž“αŸ’αžαžΉαž„αž‘αžΆαŸ†αž„αž€αžΌαžŠαžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸ αž“αž·αž„αž˜αž»αžαž„αžΆαžšαžαžΊαžŽαŸ‚αž›αžŠαŸ‚αž›αž˜αžΆαž“αž’αžΆαžŸαŸ’αžšαŸαž™αž›αžΎαž”αŸ’αžšαž—αŸαž‘αžαž˜αŸ’αžšαž„αŸ”

αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αž˜αžΆαž“αž‚αŸ„αž›αž”αŸ†αžŽαž„αž”αŸ†αž–αŸαž‰αž…αŸ†αžŽαž»αž…αžαŸ’αžœαŸ‡αžαžΆαžαž“αŸƒαžŸαž˜αŸ’αž—αžΆαžšαŸˆαž‡αžΆαž…αŸ’αžšαžΎαž“αž“αŸ…αž›αžΎ XDP αŸ” αž‘αžΈαž˜αž½αž™ αž–αž½αž€αž‚αŸαž•αŸ’αžαž›αŸ‹αž›αŸαžαž€αžΌαžŠαžŠαŸ‚αž›αžαŸ’αžšαŸ€αž˜αžšαž½αž…αž‡αžΆαžŸαŸ’αžšαŸαž…αžŠαŸ‚αž›αžšαŸ†αž›αž„αž›αž€αŸ’αžαžŽαŸˆαž–αž·αžŸαŸαžŸαžšαž”αžŸαŸ‹ XDP αž—αŸ’αž›αžΆαž˜αŸ—αŸ– αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαŸ€αž”αž…αŸ†αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹ αž¬αžŸαžΆαž˜αž‰αŸ’αž‰αž–αŸαž€αž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αž„αŸ’αž€αž”αž‰αŸ’αž αžΆαŸ” αž“αŸ…αž–αŸαž›αž’αŸ’αž“αž€αž–αŸ’αž™αžΆαž™αžΆαž˜αžŸαžšαžŸαŸαžšαž€αžΌαžŠαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž–αžΈαžŠαŸ†αž”αžΌαž„ αž’αŸ’αž“αž€αž˜αž·αž“αžŠαžΉαž„αžαžΆαžαŸ’αžšαžΌαžœαž’αŸ’αžœαžΎαž’αŸ’αžœαžΈαž‡αžΆαž˜αž½αž™αž€αŸ†αž αž»αžŸαž’αž˜αŸ’αž˜αžαžΆαž‘αŸαŸ” αž‘αžΈαž–αžΈαžš αžœαž·αž’αžΈαžŠαžΎαž˜αŸ’αž”αžΈαžŸαžΆαž€αž›αŸ’αž”αž„ XDP αž€αŸ’αž“αž»αž„αžŸαŸ’αžšαž»αž€αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“ VM αž“αž·αž„αž•αŸ’αž“αŸ‚αž€αžšαžΉαž„αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸ’αžšαž”αžŠαžŽαŸ’αžαž”αŸ‹αž‘αŸ αž”αžΎαž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž–αž½αž€αž‚αŸαž˜αžΆαž“αž€αŸ†αž αž»αžŸαž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αž€αŸαžŠαŸ„αž™αŸ” αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž˜αŸ’αžšαž»αž„αž‘αž»αž€αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αžŸαžšαžŸαŸαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ‚αž›αžŸαŸ’αž‚αžΆαž›αŸ‹αž”αžŽαŸ’αžαžΆαž‰ αž“αž·αž„αž›αžΈαž“αž»αž…αžŠαŸ‚αž›αž…αžΆαž”αŸ‹αž’αžΆαžšαž˜αŸ’αž˜αžŽαŸαž›αžΎ XDP αž“αž·αž„ eBPF αŸ”

αž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ’αž“αŸ‚αž€αž“αŸαŸ‡ αž™αžΎαž„αž“αžΉαž„αž™αž›αŸ‹αž™αŸ‰αžΆαž„αž›αž˜αŸ’αž’αž·αžαž’αŸ†αž–αžΈαžšαž”αŸ€αž”αžŠαŸ‚αž›αžαž˜αŸ’αžšαž„ XDP αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαž˜αžΌαž›αž•αŸ’αžαž»αŸ† αž“αž·αž„αžšαž”αŸ€αž”αžŸαžΆαž€αž›αŸ’αž”αž„αžœαžΆ αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž™αžΎαž„αž“αžΉαž„αžŸαžšαžŸαŸαžšαž€αŸ†αžŽαŸ‚αžŸαžΆαž˜αž‰αŸ’αž‰αž“αŸƒαž™αž“αŸ’αžαž€αžΆαžšαžαžΌαž‚αžΈ SYN αžŠαŸαž›αŸ’αž”αžΈαž›αŸ’αž”αžΆαž‰αž“αŸ…αž€αž˜αŸ’αžšαž·αžαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αŸ” αž™αžΎαž„αž“αžΉαž„αž˜αž·αž“αž”αž„αŸ’αž€αžΎαž "αž”αž‰αŸ’αž‡αžΈαžŸ" αž“αŸ…αž‘αžΎαž™αž‘αŸ
αž’αžαž·αžαž·αž‡αž“αžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹ αžšαž€αŸ’αžŸαžΆαž”αž‰αŸ’αž‡αžš αž“αž·αž„αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžαž˜αŸ’αžšαž„ - αž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹αŸ”

αž™αžΎαž„β€‹αž“αžΉαž„β€‹αžŸαžšαžŸαŸαžšβ€‹αž‡αžΆ C - αžœαžΆβ€‹αž˜αž·αž“β€‹αž‘αžΆαž“αŸ‹αžŸαž˜αŸαž™β€‹αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αžœαžΆβ€‹αž‡αžΆβ€‹αž€αžΆαžšβ€‹αž’αž“αž»αžœαžαŸ’αžβ€‹αž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αŸ” αž€αžΌαžŠαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž˜αžΆαž“αž“αŸ…αž›αžΎ GitHub αžαžΆαž˜αžšαž™αŸˆαžαŸ†αžŽαž—αŸ’αž‡αžΆαž”αŸ‹αž“αŸ…αž…αž»αž„αž”αž‰αŸ’αž…αž”αŸ‹ αž αžΎαž™αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ‚αž„αž…αŸ‚αž€αž‘αŸ…αž‡αžΆαž€αžΆαžšαž”αŸ’αžšαž–αŸ’αžšαžΉαžαŸ’αžαžαžΆαž˜αžŠαŸ†αžŽαžΆαž€αŸ‹αž€αžΆαž›αžŠαŸ‚αž›αž”αžΆαž“αž–αž·αž–αžŽαŸŒαž“αžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αŸ”

αž€αžΆαžšαž”αžŠαž·αžŸαŸαž’αŸ” αž€αŸ’αž“αž»αž„αž’αŸ†αž‘αž»αž„αž–αŸαž›αž“αŸƒαž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡ αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αž”αž„αŸ’αž€αžΎαžαžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžαŸ’αž“αžΆαžαžαžΌαž… αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž”αŸ‹αžŸαŸ’αž€αžΆαžαŸ‹αž€αžΆαžšαžœαžΆαž™αž”αŸ’αžšαž αžΆαžšαžŠαŸ„αž™ DDoS αž–αžΈαž–αŸ’αžšαŸ„αŸ‡αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž€αž·αž…αŸ’αž…αž€αžΆαžšαž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ XDP αž“αž·αž„αž•αŸ’αž“αŸ‚αž€αž‡αŸ†αž“αžΆαž‰αžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ†αŸ” αž‘αŸ„αŸ‡αž‡αžΆαž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αž‚αŸ„αž›αžŠαŸ…αžŸαŸ†αžαžΆαž“αŸ‹αž‚αžΊαžαŸ’αžšαžΌαžœαž™αž›αŸ‹αž–αžΈαž”αž…αŸ’αž…αŸαž€αžœαž·αž‘αŸ’αž™αžΆαž“αŸαŸ‡ αž˜αž·αž“αž˜αŸ‚αž“αž‡αžΆαž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ†αžŠαžΎαž˜αŸ’αž”αžΈαž”αž„αŸ’αž€αžΎαžαž€αžΆαžšαž€αžΆαžšαž–αžΆαžšαžŠαŸ‚αž›αžαŸ’αžšαŸ€αž˜αžšαž½αž…αž‡αžΆαžŸαŸ’αžšαŸαž…αž“αŸ„αŸ‡αž‘αŸαŸ” αž€αžΌαžŠαž”αž„αŸ’αžšαŸ€αž“αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαž±αŸ’αž™αž”αŸ’αžšαžŸαžΎαžšαž‘αŸ αž αžΎαž™αž›αž»αž”αž…αŸ„αž›αž“αžΌαžœαž…αŸ†αžŽαž»αž…αž˜αž½αž™αž…αŸ†αž“αž½αž“αŸ”

αž‘αž·αžŠαŸ’αž‹αž—αžΆαž–αž‘αžΌαž‘αŸ…αžŸαž„αŸ’αžαŸαž” XDP

αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αž‚αžΌαžŸαž”αž‰αŸ’αž‡αžΆαž€αŸ‹αžαŸ‚αž…αŸ†αžŽαž»αž…αžŸαŸ†αžαžΆαž“αŸ‹αŸ—αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡ αžŠαžΎαž˜αŸ’αž”αžΈαž€αž»αŸ†αž±αŸ’αž™αž…αž˜αŸ’αž›αž„αž―αž€αžŸαžΆαžš αž“αž·αž„αž’αžαŸ’αžαž”αž‘αžŠαŸ‚αž›αž˜αžΆαž“αžŸαŸ’αžšαžΆαž”αŸ‹αŸ”

αžŠαžΌαž…αŸ’αž“αŸαŸ‡ αž€αžΌαžŠαžαž˜αŸ’αžšαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž‘αž»αž€αž‘αŸ…αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž›αŸ” αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž…αžΌαž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž‘αŸ…αžαž˜αŸ’αžšαž„αŸ” αž‡αžΆαž›αž‘αŸ’αž’αž•αž› αžαž˜αŸ’αžšαž„αžαŸ’αžšαžΌαžœαžαŸ‚αž’αŸ’αžœαžΎαž€αžΆαžšαžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαŸ– αž”αž‰αŸ’αž‡αžΌαž“αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž‘αŸ…αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž› (XDP_PASS) αž‘αž˜αŸ’αž›αžΆαž€αŸ‹αž€αž‰αŸ’αž…αž”αŸ‹ (XDP_DROP) αž¬αž•αŸ’αž‰αžΎαžœαžΆαž˜αž€αžœαž·αž‰ (XDP_TX) αžαž˜αŸ’αžšαž„αž’αžΆαž…αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž€αž‰αŸ’αž…αž”αŸ‹ αž“αŸαŸ‡αž‡αžΆαž€αžΆαžšαž–αž·αžαž‡αžΆαž–αž·αžŸαŸαžŸαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ XDP_TX. αž’αŸ’αž“αž€αž€αŸαž’αžΆαž…αž”αŸ„αŸ‡αž”αž„αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ (XDP_ABORTED) αž αžΎαž™αž€αŸ†αžŽαžαŸ‹αž€αž‰αŸ’αž…αž”αŸ‹αž‘αžΎαž„αžœαž·αž‰ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αŸαŸ‡αž‚αžΊαžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆ assert(0) - αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž€αŸ‚αž€αŸ†αž αž»αžŸαŸ”

αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αž·αž˜αŸ’αž˜αž·αž eBPF (extended Berkley Packet Filter) αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž‘αžΎαž„αžŠαŸ„αž™αž…αŸαžαž“αžΆαžŸαžΆαž˜αž‰αŸ’αž‰ αžŠαžΎαž˜αŸ’αž”αžΈαž±αŸ’αž™αžαžΊαžŽαŸ‚αž›αž’αžΆαž…αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžαžΆαž€αžΌαžŠαž˜αž·αž“αžšαž„αŸ’αžœαž·αž›αž‡αž»αŸ† αž“αž·αž„αž˜αž·αž“αž’αŸ’αžœαžΎαž±αŸ’αž™αžαžΌαž…αž€αžΆαžšαž…αž„αž…αžΆαŸ†αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αžŠαž‘αŸƒαŸ” αž€αžΆαžšαžšαžΉαžαž”αž“αŸ’αžαžΉαž„ αž“αž·αž„αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž”αž“αŸ’αžαŸ‚αž˜αŸ–

  • αžšαž„αŸ’αžœαž·αž›αž‡αž»αŸ† (αžαž™αž€αŸ’αžšαŸ„αž™) αžαŸ’αžšαžΌαžœαž”αžΆαž“αž αžΆαž˜αžƒαžΆαžαŸ‹αŸ”
  • αž˜αžΆαž“αž‡αž„αŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‘αž·αž“αŸ’αž“αž“αŸαž™ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž˜αž·αž“αž˜αžΆαž“αž˜αž»αžαž„αžΆαžšαž‘αŸ (αž˜αž»αžαž„αžΆαžš C αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžαŸ’αžšαžΌαžœαžαŸ‚αžŠαžΆαž€αŸ‹αž€αŸ’αž“αž»αž„αž‡αž½αžš)αŸ”
  • αž€αžΆαžšαž…αžΌαž›αž”αŸ’αžšαžΎαž’αž„αŸ’αž‚αž…αž„αž…αžΆαŸ†αž“αŸ…αžαžΆαž„αž€αŸ’αžšαŸ…αž‡αž„αŸ‹ αž“αž·αž„αžŸαžαž·αž”αžŽαŸ’αžŠαŸ„αŸ‡αž’αžΆαžŸαž“αŸ’αž“αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž αžΆαž˜αžƒαžΆαžαŸ‹αŸ”
  • αž‘αŸ†αž αŸ†β€‹αž€αžΌαžŠβ€‹αž˜αžΆαž“β€‹αž€αž˜αŸ’αžšαž·αž αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αž€αŸ’αž“αž»αž„β€‹αž€αžΆαžšβ€‹αž’αž“αž»αžœαžαŸ’αžβ€‹αž“αŸαŸ‡β€‹αž˜αž·αž“β€‹αžŸαžΌαžœβ€‹αžŸαŸ†αžαžΆαž“αŸ‹β€‹αž‘αŸαŸ”
  • αž˜αžΆαž“αžαŸ‚αž€αžΆαžšαž αŸ…αž‘αŸ…αž€αžΆαž“αŸ‹αž˜αž»αžαž„αžΆαžšαžαžΊαžŽαŸ‚αž›αž–αž·αžŸαŸαžŸ (αž’αŸ’αž“αž€αž‡αŸ†αž“αž½αž™ eBPF) αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αž‰αŸ’αž‰αžΆαžαŸ”

αž€αžΆαžšαžšαž…αž“αžΆ αž“αž·αž„αžŠαŸ†αž‘αžΎαž„αžαž˜αŸ’αžšαž„αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž…αž“αŸαŸ‡αŸ–

  1. αž€αžΌαžŠαž”αŸ’αžšαž—αž– (ឧ kernel.c) αžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αž„αž€αŸ’αžšαž„αž‡αžΆαžœαžαŸ’αžαž» (kernel.o) αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αž·αž˜αŸ’αž˜αž·αž eBPF αŸ” αž‚αž·αžαžαŸ’αžšαžΉαž˜αžαŸ‚αžαž»αž›αžΆ αž†αŸ’αž“αžΆαŸ† 2019 αž€αžΆαžšαž…αž„αž€αŸ’αžšαž„αž‘αŸ… eBPF αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αžΆαŸ†αž‘αŸ’αžšαžŠαŸ„αž™ Clang αž“αž·αž„αž”αžΆαž“αžŸαž“αŸ’αž™αžΆαž“αŸ…αž€αŸ’αž“αž»αž„ GCC 10.1 αŸ”
  2. αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž€αžΌαžŠαžœαžαŸ’αžαž»αž“αŸαŸ‡αž˜αžΆαž“αž€αžΆαžšαž αŸ…αž‘αŸ…αž€αžΆαž“αŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αžαžΊαžŽαŸ‚αž› (αž§αž‘αžΆαž αžšαžŽαŸ αžαžΆαžšαžΆαž„ αž“αž·αž„αž”αž‰αŸ’αž‡αžš) αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαžαŸ’αžšαžΌαžœαž”αžΆαž“αž‡αŸ†αž“αž½αžŸαžŠαŸ„αž™αž›αŸαžαžŸαžΌαž“αŸ’αž™ αžŠαŸ‚αž›αž˜αžΆαž“αž“αŸαž™αžαžΆαž€αžΌαžŠαž”αŸ‚αž”αž“αŸαŸ‡αž˜αž·αž“αž’αžΆαž…αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž”αžΆαž“αž‘αŸαŸ” αž˜αž»αž“αž–αŸαž›αž•αŸ’αž‘αž»αž€αž‘αŸ…αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž› αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž‡αŸ†αž“αž½αžŸαž›αŸαžαžŸαžΌαž“αŸ’αž™αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž“αŸƒαžœαžαŸ’αžαž»αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αžŠαŸ‚αž›αž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαžαžΆαž˜αžšαž™αŸˆαž€αžΆαžšαž αŸ…αž‘αžΌαžšαžŸαŸαž–αŸ’αž‘αžαžΊαžŽαŸ‚αž› (αž—αŸ’αž‡αžΆαž”αŸ‹αž€αžΌαžŠ)αŸ” αž’αŸ’αž“αž€αž’αžΆαž…αž’αŸ’αžœαžΎαžŠαžΌαž…αž“αŸαŸ‡αž‡αžΆαž˜αž½αž™αž§αž”αž€αžšαžŽαŸαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžαžΆαž„αž€αŸ’αžšαŸ… αž¬αž’αŸ’αž“αž€αž’αžΆαž…αžŸαžšαžŸαŸαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ‚αž›αž“αžΉαž„αž—αŸ’αž‡αžΆαž”αŸ‹ αž“αž·αž„αž•αŸ’αž‘αž»αž€αžαž˜αŸ’αžšαž„αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αž˜αž½αž™αŸ”
  3. αžαžΊαžŽαŸ‚αž›αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‘αž»αž€αŸ” αž’αžœαžαŸ’αžŠαž˜αžΆαž“αž“αŸƒαžœαžŠαŸ’αž αž“αž·αž„αž€αžΆαžšαž”αžšαžΆαž‡αŸαž™αž€αŸ’αž“αž»αž„αž€αžΆαžšαž›αžΎαžŸαž–αžΈαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ αž“αž·αž„αž–αŸ’αžšαŸ†αžŠαŸ‚αž“αž‡αž„αŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž–αž·αž“αž·αžαŸ’αž™αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž˜αž·αž“αž’αžΆαž…αž”αž„αŸ’αž αžΆαž‰αžαžΆαž›αŸαžαž€αžΌαžŠαžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœαž‘αŸ αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αžŠαž·αžŸαŸαž’ - αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαžαŸ‚αž’αžΆαž…αž•αŸ’αž‚αžΆαž”αŸ‹αž…αž·αžαŸ’αžαž‚αžΆαžαŸ‹αŸ”
  4. αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αžŠαŸ„αž™αž‡αŸ„αž‚αž‡αŸαž™ αžαžΊαžŽαŸ‚αž›αž…αž„αž€αŸ’αžšαž„αž€αžΌαžŠαžœαžαŸ’αžαž»αžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜ eBPF αž‘αŸ…αž‡αžΆαž€αžΌαžŠαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’ (αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž“αŸ…αž€αŸ’αž“αž»αž„αž–αŸαž›αžœαŸαž›αžΆ)αŸ”
  5. αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž—αŸ’αž‡αžΆαž”αŸ‹αž‘αŸ…αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹ αž αžΎαž™αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αŸ”

αž…αžΆαž”αŸ‹αžαžΆαŸ†αž„αž–αžΈ XDP αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸ…αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž› αž€αžΆαžšαž”αŸ†αž”αžΆαžαŸ‹αž€αŸ†αž αž»αžŸαžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαžŠαŸ„αž™αž”αŸ’αžšαžΎαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αžαžΆαž˜αžŠαžΆαž“ αž αžΎαž™αž‡αžΆαž€αžΆαžšαž–αž·αž αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αžŠαŸ‚αž›αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž…αž˜αŸ’αžšαŸ„αŸ‡ αž¬αž”αž„αŸ’αž€αžΎαžαŸ” αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ eBPF αž’αžΆαž“αžΆαžαžΆαž€αžΌαžŠαžŠαŸ‚αž›αž”αžΆαž“αž‘αžΆαž‰αž™αž€αž‚αžΊαž˜αžΆαž“αžŸαž»αžœαžαŸ’αžαž·αž—αžΆαž–αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž”αŸ’αžšαž–αŸαž“αŸ’αž’ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž’αŸ’αž“αž€αž’αžΆαž…αž–αž·αžŸαŸ„αž’αž“αŸαž‡αžΆαž˜αž½αž™ XDP αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž“αŸ…αž›αžΎαž›αžΈαž“αž»αž…αž€αŸ’αž“αž»αž„αžŸαŸ’αžšαž»αž€αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”

αž€αžΆαžšαžšαŸ€αž”αž…αŸ†αž”αžšαž·αžŸαŸ’αžαžΆαž“

αžŸαž“αŸ’αž“αž·αž”αžΆαž

Clang αž˜αž·αž“αž’αžΆαž…αž”αž„αŸ’αž€αžΎαžαž€αžΌαžŠαžœαžαŸ’αžαž»αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜ eBPF αž”αžΆαž“αž‘αŸ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αžΆαž“αž–αžΈαžšαž‡αŸ†αž αžΆαž“αŸ–

  1. αž…αž„αž€αŸ’αžšαž„αž€αžΌαžŠ C αž‘αŸ…αž‡αžΆ LLVM bytecode (clang -emit-llvm).
  2. αž”αŸ†αž›αŸ‚αž„ bytecode αž‘αŸ… eBPF object code (llc -march=bpf -filetype=obj).

αž“αŸ…αž–αŸαž›αžŸαžšαžŸαŸαžšαžαž˜αŸ’αžšαž„ αž―αž€αžŸαžΆαžšαž–αžΈαžšαž”αžΈαžŠαŸ‚αž›αž˜αžΆαž“αž˜αž»αžαž„αžΆαžšαž‡αŸ†αž“αž½αž™ αž“αž·αž„αž˜αŸ‰αžΆαž€αŸ’αžšαžΌαž“αžΉαž„αž˜αžΆαž“αž”αŸ’αžšαž™αŸ„αž‡αž“αŸ αž–αžΈαž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαžαžΊαžŽαŸ‚αž›αŸ”. αžœαžΆαžŸαŸ†αžαžΆαž“αŸ‹αžŽαžΆαžŸαŸ‹αžŠαŸ‚αž›αž–αž½αž€αžœαžΆαžαŸ’αžšαžΌαžœαž‚αŸ’αž“αžΆαž“αžΉαž„αž€αŸ†αžŽαŸ‚αžαžΊαžŽαŸ‚αž› (KVER) αž‘αžΆαž‰αž™αž€αž–αž½αž€αžœαžΆαž‘αŸ… helpers/:

export KVER=v5.3.7
export BASE=https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/plain/tools/testing/selftests/bpf
wget -P helpers --content-disposition "${BASE}/bpf_helpers.h?h=${KVER}" "${BASE}/bpf_endian.h?h=${KVER}"
unset KVER BASE

Makefile αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Arch Linux (αžαžΊαžŽαŸ‚αž› 5.3.7)αŸ–

CLANG ?= clang
LLC ?= llc

KDIR ?= /lib/modules/$(shell uname -r)/build
ARCH ?= $(subst x86_64,x86,$(shell uname -m))

CFLAGS = 
    -Ihelpers 
    
    -I$(KDIR)/include 
    -I$(KDIR)/include/uapi 
    -I$(KDIR)/include/generated/uapi 
    -I$(KDIR)/arch/$(ARCH)/include 
    -I$(KDIR)/arch/$(ARCH)/include/generated 
    -I$(KDIR)/arch/$(ARCH)/include/uapi 
    -I$(KDIR)/arch/$(ARCH)/include/generated/uapi 
    -D__KERNEL__ 
    
    -fno-stack-protector -O2 -g

xdp_%.o: xdp_%.c Makefile
    $(CLANG) -c -emit-llvm $(CFLAGS) $< -o - | 
    $(LLC) -march=bpf -filetype=obj -o $@

.PHONY: all clean

all: xdp_filter.o

clean:
    rm -f ./*.o

KDIR αž˜αžΆαž“αž•αŸ’αž›αžΌαžœαž‘αŸ…αž€αžΆαž“αŸ‹αž”αž‹αž˜αž€αžαžΆαžαžΊαžŽαŸ‚αž› ARCH - αžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’αŸ” αž•αŸ’αž›αžΌαžœ αž“αž·αž„αž§αž”αž€αžšαžŽαŸαž’αžΆαž…αž”αŸ’αžšαŸ‚αž”αŸ’αžšαž½αž›αž”αž“αŸ’αžαž·αž…αž”αž“αŸ’αžαž½αž…αžšαžœαžΆαž„αž€αžΆαžšαž…αŸ‚αž€αž…αžΆαž™αŸ”

αž§αž‘αžΆαž αžšαžŽαŸαž“αŸƒαž—αžΆαž–αžαž»αžŸαž‚αŸ’αž“αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Debian 10 (αžαžΊαžŽαŸ‚αž› 4.19.67)

# другая ΠΊΠΎΠΌΠ°Π½Π΄Π°
CLANG ?= clang
LLC ?= llc-7

# Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³
KDIR ?= /usr/src/linux-headers-$(shell uname -r)
ARCH ?= $(subst x86_64,x86,$(shell uname -m))

# Π΄Π²Π° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π° -I
CFLAGS = 
    -Ihelpers 
    
    -I/usr/src/linux-headers-4.19.0-6-common/include 
    -I/usr/src/linux-headers-4.19.0-6-common/arch/$(ARCH)/include 
    # Π΄Π°Π»Π΅Π΅ Π±Π΅Π· ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ

CFLAGS αž—αŸ’αž‡αžΆαž”αŸ‹β€‹αžαžβ€‹αž‡αžΆαž˜αž½αž™β€‹αž”αž‹αž˜αž€αžαžΆβ€‹αž‡αŸ†αž“αž½αž™ αž“αž·αž„β€‹αžαžβ€‹αž˜αž½αž™β€‹αž…αŸ†αž“αž½αž“β€‹αž‡αžΆαž˜αž½αž™β€‹αž”αž‹αž˜αž€αžαžΆβ€‹αžαžΊαžŽαŸ‚αž›αŸ” αž“αž·αž˜αž·αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆ __KERNEL__ αž˜αžΆαž“αž“αŸαž™αžαžΆ αž”αž‹αž˜αž€αžαžΆ UAPI (userspace API) αžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΌαžŠαžαžΊαžŽαŸ‚αž› αž…αžΆαž”αŸ‹αžαžΆαŸ†αž„αž–αžΈαžαž˜αŸ’αžšαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž›αŸ”

αž€αžΆαžšαž€αžΆαžšαž–αžΆαžšαž‡αž„αŸ‹αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž·αž‘ (-fno-stack-protector) αžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚αž’αŸ’αž“αž€αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž›αŸαžαž€αžΌαžŠ eBPF αž“αŸ…αžαŸ‚αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αž€αžΆαžšαž”αŸ†αž–αžΆαž“αž›αžΎαž€αžΆαžšαž‡αž„αŸ‹αŸ” αžœαžΆαž˜αžΆαž“αžαž˜αŸ’αž›αŸƒαž”αžΎαž€αž€αžΆαžšαž”αž„αŸ’αž€αžΎαž“αž”αŸ’αžšαžŸαž·αž‘αŸ’αž’αž—αžΆαž–αž—αŸ’αž›αžΆαž˜αŸ— αž–αžΈαž–αŸ’αžšαŸ„αŸ‡αž‘αŸ†αž αŸ†αž“αŸƒαž›αŸαžαž€αžΌαžŠ eBPF αž˜αžΆαž“αž€αŸ†αžŽαžαŸ‹αŸ”

αž…αžΌαžšαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž‡αžΆαž˜αž½αž™αžαž˜αŸ’αžšαž„αžŠαŸ‚αž›αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αž€αž‰αŸ’αž…αž”αŸ‹αž‘αžΆαŸ†αž„αž’αžŸαŸ‹ αž αžΎαž™αž˜αž·αž“αž’αŸ’αžœαžΎαž’αŸ’αžœαžΈαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αŸ–

#include <uapi/linux/bpf.h>

#include <bpf_helpers.h>

SEC("prog")
int xdp_main(struct xdp_md* ctx) {
    return XDP_PASS;
}

char _license[] SEC("license") = "GPL";

αž€αŸ’αžšαž»αž˜αž€αžΆαžšαž„αžΆαžš make αž”αŸ’αžšαž˜αžΌαž› xdp_filter.o. αžŸαžΆαž€αž›αŸ’αž”αž„αž“αŸ…αž―αžŽαžΆαž₯αž‘αžΌαžœαž“αŸαŸ‡?

αžˆαžšαžŸαžΆαž€αž›αŸ’αž”αž„

αž€αž“αŸ’αž›αŸ‚αž„αžˆαžšαžαŸ’αžšαžΌαžœαžαŸ‚αžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž–αžΈαžšαŸ– αžŠαŸ‚αž›αž“αžΉαž„αž˜αžΆαž“αžαž˜αŸ’αžšαž„ αž“αž·αž„αž–αžΈαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αžŽαžΆαž˜αž½αž™αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž‰αžΎαŸ” αž‘αžΆαŸ†αž„αž“αŸαŸ‡αžαŸ’αžšαžΌαžœαžαŸ‚αž‡αžΆαž§αž”αž€αžšαžŽαŸαž›αžΈαž“αž»αž…αž–αŸαž‰αž›αŸαž‰αž‡αžΆαž˜αž½αž™αž“αžΉαž„ IPs αž•αŸ’αž‘αžΆαž›αŸ‹αžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸ αžŠαžΎαž˜αŸ’αž”αžΈαž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžαžΆαžαžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž’αž˜αŸ’αž˜αžαžΆαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‡αžΆαž˜αž½αž™αžαž˜αŸ’αžšαž„αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ”

αž§αž”αž€αžšαžŽαŸαž“αŸƒαž”αŸ’αžšαž—αŸαž‘ veth (virtual Ethernet) αž‚αžΊαžŸαž˜αžšαž˜αŸ’αž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž™αžΎαž„αŸ– αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž‚αžΌαž“αŸƒαž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž”αžŽαŸ’αžαžΆαž‰αž“αž·αž˜αŸ’αž˜αž·αž "αž”αžΆαž“αž—αŸ’αž‡αžΆαž”αŸ‹" αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž‘αŸ…αž‚αŸ’αž“αžΆαž‘αŸ…αžœαž·αž‰αž‘αŸ…αž˜αž€αŸ” αž’αŸ’αž“αž€αž’αžΆαž…αž”αž„αŸ’αž€αžΎαžαž–αž½αž€αžœαžΆαžŠαžΌαž…αž“αŸαŸ‡ (αž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ’αž“αŸ‚αž€αž“αŸαŸ‡ αž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αŸ” ip αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαž–αžΈ root):

ip link add xdp-remote type veth peer name xdp-local

αžœαžΆαž‚αžΊαž‡αžΆαž€αžΆαžš xdp-remote ΠΈ xdp-local - αžˆαŸ’αž˜αŸ„αŸ‡αž§αž”αž€αžšαžŽαŸαŸ” αž”αžΎαž€ xdp-local (192.0.2.1/24) αžαž˜αŸ’αžšαž„αž˜αž½αž™αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž—αŸ’αž‡αžΆαž”αŸ‹αž‡αžΆαž˜αž½αž™ xdp-remote (192.0.2.2/24) αž…αžšαžΆαž…αžšαžŽαŸαž…αžΌαž›αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž‰αžΎαŸ” αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αž˜αžΆαž“αž”αž‰αŸ’αž αžΆαž˜αž½αž™αŸ– αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž‚αžΊαž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžαŸ‚αž˜αž½αž™ αž αžΎαž™αž›αžΈαž“αž»αž…αž“αžΉαž„αž˜αž·αž“αž”αž‰αŸ’αž‡αžΌαž“αž…αžšαžΆαž…αžšαž‘αŸ…αž€αžΆαž“αŸ‹αž˜αž½αž™αž€αŸ’αž“αž»αž„αž…αŸ†αžŽαŸ„αž˜αž–αž½αž€αžœαžΆαžαžΆαž˜αžšαž™αŸˆαž§αž”αž€αžšαžŽαŸαž•αŸ’αžŸαŸαž„αž‘αŸ€αžαŸ” αž’αŸ’αž“αž€αž’αžΆαž…αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžœαžΆαžŠαŸ„αž™αž”αŸ’αžšαžΎαž…αŸ’αž”αžΆαž”αŸ‹αž›αŸ’αž”αž·αž… iptablesαž”αŸ‰αž»αž“αŸ’αžαŸ‚αž–αž½αž€αž‚αŸαž“αžΉαž„αžαŸ’αžšαžΌαžœαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž€αž‰αŸ’αž…αž”αŸ‹ αžŠαŸ‚αž›αž‡αžΆαž€αžΆαžšαžšαž’αžΆαž€αŸ‹αžšαž’αž½αž›αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž€αŸ‚αž€αŸ†αž αž»αžŸαŸ” αžœαžΆαž‡αžΆαž€αžΆαžšαž”αŸ’αžšαžŸαžΎαžšαž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αŸ’αžšαžΎαž…αž“αŸ’αž›αŸ„αŸ‡αžˆαŸ’αž˜αŸ„αŸ‡αž”αžŽαŸ’αžαžΆαž‰ (αž”αž“αŸ’αž‘αžΆαž”αŸ‹ netns) αŸ”

αž…αž“αŸ’αž›αŸ„αŸ‡αžˆαŸ’αž˜αŸ„αŸ‡αž”αžŽαŸ’αžαžΆαž‰αž˜αžΆαž“αžŸαŸ†αžŽαž»αŸ†αž“αŸƒαž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹ αžαžΆαžšαžΆαž„αž“αžΆαŸ†αž•αŸ’αž›αžΌαžœ αž“αž·αž„αž…αŸ’αž”αžΆαž”αŸ‹ NetFilter αžŠαŸ‚αž›αžŠαžΆαž…αŸ‹αž†αŸ’αž„αžΆαž™αž–αžΈαžœαžαŸ’αžαž»αžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆαž“αŸ…αž€αŸ’αž“αž»αž„ netns αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαŸ” αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αžΈαž˜αž½αž™αŸ—αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αŸ’αž“αž»αž„ namespace αž αžΎαž™αž˜αžΆαž“αžŸαž·αž‘αŸ’αž’αž·αž…αžΌαž›αž”αŸ’αžšαžΎαžαŸ‚αžœαžαŸ’αžαž»αž“αŸƒ netns αž“αŸ„αŸ‡αŸ” αžαžΆαž˜αž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜ αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž˜αžΆαž“αž›αŸ†αž αž”αžŽαŸ’αžαžΆαž‰αžαŸ‚αž˜αž½αž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžœαžαŸ’αžαž»αž‘αžΆαŸ†αž„αž’αžŸαŸ‹ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž’αŸ’αž“αž€αž’αžΆαž…αž’αŸ’αžœαžΎαž€αžΆαžšαž“αŸ…αž€αŸ’αž“αž»αž„αž›αžΈαž“αž»αž… αž αžΎαž™αž˜αž·αž“αžŠαžΉαž„αž’αŸ†αž–αžΈ netns αž‘αŸαŸ”

αžαŸ„αŸ‡αž”αž„αŸ’αž€αžΎαž namespace αžαŸ’αž˜αžΈαŸ” xdp-test αž αžΎαž™αž•αŸ’αž›αžΆαžŸαŸ‹αž‘αžΈαžœαžΆαž‘αŸ…αž‘αžΈαž“αŸ„αŸ‡ xdp-remote.

ip netns add xdp-test
ip link set dev xdp-remote netns xdp-test

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ†αžŽαžΎαžšαž€αžΆαžš xdp-testαž“αžΉαž„αž˜αž·αž“ "αžƒαžΎαž‰" xdp-local (αžœαžΆαž“αžΉαž„αž“αŸ…αžαŸ‚αž˜αžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„ netns αžαžΆαž˜αž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜) αž αžΎαž™αž“αŸ…αž–αŸαž›αž•αŸ’αž‰αžΎαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž‘αŸ… 192.0.2.1 αžœαžΆαž“αžΉαž„αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αžœαžΆ xdp-remoteαžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚αžœαžΆαž‡αžΆαž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αžαŸ‚αž˜αž½αž™αž‚αžαŸ‹αž“αŸ…αž›αžΎ 192.0.2.0/24 αž’αžΆαž…αž…αžΌαž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž”αžΆαž“αž€αŸ’αž“αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸαŸ‡αŸ” αž“αŸαŸ‡αž€αŸαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αŸ’αž“αž»αž„αž‘αž·αžŸαžŠαŸ…αž•αŸ’αž‘αž»αž™αŸ”

αž“αŸ…αž–αŸαž›αž•αŸ’αž›αžΆαžŸαŸ‹αž‘αžΈαžšαžœαžΆαž„ netns αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž’αŸ’αž›αžΆαž€αŸ‹αž…αž»αŸ‡ αž αžΎαž™αž”αžΆαžαŸ‹αž”αž„αŸ‹αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αžšαž”αžŸαŸ‹αžœαžΆαŸ” αžŠαžΎαž˜αŸ’αž”αžΈαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„ netns αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαžŠαŸ†αžŽαžΎαžšαž€αžΆαžš ip ... αž“αŸ…αž€αŸ’αž“αž»αž„ namespace αž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαž“αŸαŸ‡αŸ” ip netns exec:

ip netns exec xdp-test 
    ip address add 192.0.2.2/24 dev xdp-remote
ip netns exec xdp-test 
    ip link set xdp-remote up

αžŠαžΌαž…αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αžƒαžΎαž‰αžœαžΆαž˜αž·αž“αžαž»αžŸαž–αžΈαž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αž‘αŸαŸ” xdp-local αž“αŸ…αž€αŸ’αž“αž»αž„ namespace αž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜αŸ–

    ip address add 192.0.2.1/24 dev xdp-local
    ip link set xdp-local up

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αžšαžαŸ‹ tcpdump -tnevi xdp-localαž’αŸ’αž“αž€αž’αžΆαž…αž˜αžΎαž›αžƒαžΎαž‰αžαžΆαž€αž‰αŸ’αž…αž”αŸ‹αžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‰αžΎαž–αžΈ xdp-testαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž‘αŸ…αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž“αŸαŸ‡αŸ–

ip netns exec xdp-test   ping 192.0.2.1

αžœαžΆαž„αžΆαž™αžŸαŸ’αžšαž½αž›αž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αžΎαž€αžŸαŸ‚αž›αž…αžΌαž› xdp-test. αžƒαŸ’αž›αžΆαŸ†αž„αž˜αžΆαž“αžŸαŸ’αž‚αŸ’αžšαžΈαž”αžŠαŸ‚αž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž‡αžΆαž˜αž½αž™ stand; αž§αž‘αžΆαž αžšαžŽαŸ αž’αŸ’αž“αž€αž’αžΆαž…αž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αžˆαžšαžŠαŸ„αž™αž”αŸ’αžšαžΎαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆ sudo ./stand up αž αžΎαž™αž›αž»αž”αžœαžΆαž…αŸ„αž› sudo ./stand down.

αž€αžΆαžšαžαžΆαž˜αžŠαžΆαž“

αžαž˜αŸ’αžšαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž—αŸ’αž‡αžΆαž”αŸ‹αž‡αžΆαž˜αž½αž™αž§αž”αž€αžšαžŽαŸαžŠαžΌαž…αž“αŸαŸ‡αŸ–

ip -force link set dev xdp-local xdp object xdp_filter.o verbose

αž‚αž“αŸ’αž›αžΉαŸ‡ -force αžαŸ’αžšαžΌαžœαž€αžΆαžšαžŠαžΎαž˜αŸ’αž”αžΈαž—αŸ’αž‡αžΆαž”αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαŸ’αž˜αžΈ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž˜αž½αž™αž‘αŸ€αžαžαŸ’αžšαžΌαžœαž”αžΆαž“αž—αŸ’αž‡αžΆαž”αŸ‹αžšαž½αž…αž αžΎαž™αŸ” "αž‚αŸ’αž˜αžΆαž“αž–αŸαžαŸŒαž˜αžΆαž“αž‡αžΆαžŠαŸ†αžŽαžΉαž„αž›αŸ’αž’αž‘αŸ" αž˜αž·αž“αž˜αŸ‚αž“αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαž“αŸαŸ‡αž‘αŸ αž€αžΆαžšαžŸαž“αŸ’αž“αž·αžŠαŸ’αž‹αžΆαž“αž‚αžΊαž’αžŸαŸ’αž…αžΆαžšαŸ’αž™αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαžŽαžΆαž˜αž½αž™αŸ” αž…αž„αŸ’αž’αž»αž›αž”αž„αŸ’αž αžΆαž‰ verbose αžŸαŸ’αžšαŸαž…αž…αž·αžαŸ’αž αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž‡αžΆαž˜αž½αž™αžœαžΆ αžšαž”αžΆαž™αž€αžΆαžšαžŽαŸαž˜αž½αž™αž“αžΉαž„αž›αŸαž…αž‘αžΎαž„αž“αŸ…αž›αžΎαž€αžΆαžšαž„αžΆαžšαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž€αžΌαžŠαž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž…αž»αŸ‡αž”αž‰αŸ’αž‡αžΈαž€αžΆαžšαž‡αž½αž”αž”αŸ’αžšαž‡αž»αŸ†αž‚αŸ’αž“αžΆαž˜αž½αž™αŸ–

Verifier analysis:

0: (b7) r0 = 2
1: (95) exit

αž•αŸ’αžαžΆαž…αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž–αžΈαž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αŸ–

ip link set dev xdp-local xdp off

αž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ’αž‚αŸ’αžšαžΈαž”αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆ sudo ./stand attach ΠΈ sudo ./stand detach.

αžαžΆαž˜αžšαž™αŸˆαž€αžΆαžšαž—αŸ’αž‡αžΆαž”αŸ‹αžαž˜αŸ’αžšαž„ αž’αŸ’αž“αž€αž’αžΆαž…αž”αŸ’αžšαžΆαž€αžŠαžαžΆαžœαžΆαŸ” ping αž”αž“αŸ’αžαžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‘αŸ? αžαŸ„αŸ‡αž”αž“αŸ’αžαŸ‚αž˜αž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αŸ” αž˜αž»αžαž„αžΆαžš bpf_trace_printk() αžŸαŸ’αžšαžŠαŸ€αž„αž‘αŸ…αž“αžΉαž„ printf()αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž‚αžΆαŸ†αž‘αŸ’αžšαžαŸ‚αž’αžΆαž‚αž»αž™αž˜αŸ‰αž„αŸ‹αž”αžΈαž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡ αž€αŸ’αžšαŸ…αž–αžΈαž‚αŸ†αžšαžΌ αž“αž·αž„αž”αž‰αŸ’αž‡αžΈαž€αŸ†αžŽαžαŸ‹αž“αŸƒαž’αŸ’αž“αž€αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αŸ” αž˜αŸ‰αžΆαž€αŸ’αžšαžΌ bpf_printk() αžŸαž˜αŸ’αžšαž½αž›αž€αžΆαžšαž αŸ…αž‘αžΌαžšαžŸαž–αŸ’αž‘αŸ”

   SEC("prog")
   int xdp_main(struct xdp_md* ctx) {
+      bpf_printk("got packet: %pn", ctx);
       return XDP_PASS;
   }

αž›αž‘αŸ’αž’αž•αž›β€‹αž‘αŸ…β€‹αž†αžΆαž“αŸ‚αž›β€‹αžŠαžΆαž“β€‹αžαžΊαžŽαŸ‚αž› αžŠαŸ‚αž›β€‹αžαŸ’αžšαžΌαžœβ€‹αž”αžΎαž€αŸ–

echo -n 1 | sudo tee /sys/kernel/debug/tracing/options/trace_printk

αž˜αžΎαž›β€‹αž’αžαŸ’αžαž”αž‘β€‹αžŸαžΆαžšαŸ–

cat /sys/kernel/debug/tracing/trace_pipe

αž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαž‘αžΆαŸ†αž„αž–αžΈαžšαž“αŸαŸ‡αž’αŸ’αžœαžΎαž€αžΆαžšαž αŸ…αž‘αžΌαžšαžŸαž–αŸ’αž‘ sudo ./stand log.

Ping αž‚αž½αžšαžαŸ‚αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžŸαžΆαžšαžŠαžΌαž…αž“αŸαŸ‡αŸ–

<...>-110930 [004] ..s1 78803.244967: 0: got packet: 00000000ac510377

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž€αŸ’αžšαž‘αŸαž€αž˜αžΎαž›αž›αž‘αŸ’αž’αž•αž›αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž±αŸ’αž™αž”αžΆαž“αžŠαž·αžαžŠαž›αŸ‹ αž’αŸ’αž“αž€αž“αžΉαž„αžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αžƒαžΎαž‰αž€αžΆαžšαž‚αžŽαž“αžΆαž…αž˜αŸ’αž›αŸ‚αž€αŸ–

0: (bf) r3 = r1
1: (18) r1 = 0xa7025203a7465
3: (7b) *(u64 *)(r10 -8) = r1
4: (18) r1 = 0x6b63617020746f67
6: (7b) *(u64 *)(r10 -16) = r1
7: (bf) r1 = r10
8: (07) r1 += -16
9: (b7) r2 = 16
10: (85) call bpf_trace_printk#6
<...>

αž€αžΆαžšαž–αž·αžαž‚αžΊαžαžΆαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ eBPF αž˜αž·αž“αž˜αžΆαž“αž•αŸ’αž“αŸ‚αž€αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‘αŸ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžœαž·αž’αžΈαžαŸ‚αž˜αž½αž™αž‚αžαŸ‹αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸŠαž·αž“αž€αžΌαžŠαžαŸ’αžŸαŸ‚αž’αž€αŸ’αžŸαžšαž‘αŸ’αžšαž„αŸ‹αž‘αŸ’αžšαžΆαž™αž‚αžΊαž‡αžΆαž’αžΆαž‚αž»αž™αž˜αŸ‰αž„αŸ‹αž—αŸ’αž›αžΆαž˜αŸ—αž“αŸƒαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆ VMαŸ–

$ python -c "import binascii; print(bytes(reversed(binascii.unhexlify('0a7025203a74656b63617020746f67'))))"
b'got packet: %pn'

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž αŸαžαž»αž•αž›αž“αŸαŸ‡ αž›αž‘αŸ’αž’αž•αž›αž”αŸ†αž”αžΆαžαŸ‹αž€αŸ†αž αž»αžŸαž’αŸ’αžœαžΎαž±αŸ’αž™αž€αžΌαžŠαž›αž‘αŸ’αž’αž•αž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž™αŸ‰αžΆαž„αžαŸ’αž›αžΆαŸ†αž„αŸ”

αž€αŸ†αž–αž»αž„αž•αŸ’αž‰αžΎαž€αž‰αŸ’αž…αž”αŸ‹ XDP

αžαŸ„αŸ‡αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαžαž˜αŸ’αžšαž„αŸ– αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αžœαžΆαž”αž‰αŸ’αž‡αžΌαž“αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž…αžΌαž›αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αŸ” αž“αŸαŸ‡αž˜αž·αž“αžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœαžαžΆαž˜αž‘αžŸαŸ’αžŸαž“αŸˆαžšαž”αžŸαŸ‹αž”αžŽαŸ’αžαžΆαž‰ αž–αŸ’αžšαŸ„αŸ‡αžαžΆαžœαžΆαž…αžΆαŸ†αž”αžΆαž…αŸ‹αž€αŸ’αž“αž»αž„αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„αž”αž‹αž˜αž€αžαžΆ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž₯αž‘αžΌαžœαž“αŸαŸ‡αž€αžΆαžšαž„αžΆαžšαž‡αžΆαž‚αŸ„αž›αž€αžΆαžšαžŽαŸαž˜αžΆαž“αžŸαžΆαžšαŸˆαžŸαŸ†αžαžΆαž“αŸ‹αŸ”

       bpf_printk("got packet: %pn", ctx);
-      return XDP_PASS;
+      return XDP_TX;
   }

αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš tcpdump αž“αŸ…αž›αžΎ xdp-remote. αžœαžΆαž‚αž½αžšαžαŸ‚αž”αž„αŸ’αž αžΆαž‰ ICMP Echo Request αž…αŸαž‰ αž“αž·αž„αž…αžΌαž›αžŠαžΌαž…αž‚αŸ’αž“αžΆ αž αžΎαž™αžˆαž”αŸ‹αž”αž„αŸ’αž αžΆαž‰ ICMP Echo Reply αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžœαžΆαž˜αž·αž“αž”αž„αŸ’αž αžΆαž‰αž‘αŸαŸ” αžœαžΆαž”αŸ’αžšαŸ‚αžαžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž„αžΆαžš XDP_TX αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž“αŸ…αž›αžΎ xdp-local αž‚αžΊαž…αžΆαŸ†αž”αžΆαž…αŸ‹αž‘αŸ…αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž‚αžΌ xdp-remote αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž˜αž½αž™αž€αŸαžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αžΆαžαŸ‹αžαžΆαŸ†αž„αž•αž„αžŠαŸ‚αžš αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαžœαžΆαž‘αž‘αŸαž€αŸαžŠαŸ„αž™ αž αžΎαž™αž‚αžΆαžαŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž›αžΎαž€αž‘αžΎαž„αŸ”

αžαžΎαžαŸ’αž‰αž»αŸ†αžŠαžΉαž„αžšαžΏαž„αž“αŸαŸ‡αžŠαŸ„αž™αžšαž”αŸ€αž”αžŽαžΆ?

αžαžΆαž˜αžŠαžΆαž“αž•αŸ’αž›αžΌαžœαž“αŸƒαž€αž‰αŸ’αž…αž”αŸ‹αž˜αž½αž™αž“αŸ…αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž›αŸ” αž™αž“αŸ’αžαž€αžΆαžšαž–αŸ’αžšαžΉαžαŸ’αžαž·αž€αžΆαžšαžŽαŸ perf αž’αž“αž»αž‰αŸ’αž‰αžΆαžαžŠαŸ„αž™αžœαž·αž’αžΈαž“αŸαŸ‡ αžŠαŸ„αž™αž”αŸ’αžšαžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αž·αž˜αŸ’αž˜αž·αžαžŠαžΌαž…αž‚αŸ’αž“αžΆ αž–αŸ„αž›αž‚αžΊ eBPF αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžšαž»αŸ‡αžšαžΎαž‡αžΆαž˜αž½αž™ eBPF αŸ”

αž’αŸ’αž“αž€β€‹αžαŸ’αžšαžΌαžœβ€‹αž’αŸ’αžœαžΎβ€‹αž’αŸ†αž–αžΎβ€‹αž›αŸ’αž’β€‹αž…αŸαž‰β€‹αž–αžΈβ€‹αž’αŸ†αž–αžΎβ€‹αž’αžΆαž€αŸ’αžšαž€αŸ‹ αž–αŸ’αžšαŸ„αŸ‡β€‹αž‚αŸ’αž˜αžΆαž“β€‹αž’αŸ’αžœαžΈβ€‹αž•αŸ’αžŸαŸαž„β€‹αž‘αŸ€αžβ€‹αžŠαŸ‚αž›β€‹αž’αžΆαž…β€‹αž’αŸ’αžœαžΎβ€‹αž”αžΆαž“β€‹αž‘αžΎαž™αŸ”

$ sudo perf trace --call-graph dwarf -e 'xdp:*'
   0.000 ping/123455 xdp:xdp_bulk_tx:ifindex=19 action=TX sent=0 drops=1 err=-6
                                     veth_xdp_flush_bq ([veth])
                                     veth_xdp_flush_bq ([veth])
                                     veth_poll ([veth])
                                     <...>

αžαžΎαž›αŸαžαž€αžΌαžŠ ៦ αž‡αžΆαž’αŸ’αžœαžΈ?

$ errno 6
ENXIO 6 No such device or address

αž˜αž»αžαž„αžΆαžš veth_xdp_flush_bq() αž‘αž‘αž½αž›αž”αžΆαž“αž›αŸαžαž€αžΌαžŠαž€αŸ†αž αž»αžŸαž–αžΈ veth_xdp_xmit()αžŠαŸ‚αž›αž‡αžΆαž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αžŸαŸ’αžœαŸ‚αž„αžšαž€αžŠαŸ„αž™ ENXIO αž“αž·αž„αžŸαŸ’αžœαŸ‚αž„αžšαž€αž˜αžαž·αž™αŸ„αž”αž›αŸ‹αŸ”

αžαŸ„αŸ‡αžŸαŸ’αžαžΆαžšαžαž˜αŸ’αžšαž„αž’αž”αŸ’αž”αž”αžšαž˜αžΆ (XDP_PASS) αž“αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžš xdp_dummy.cαž”αž“αŸ’αžαŸ‚αž˜αžœαžΆαž‘αŸ… Makefile αž…αž„αžœαžΆαž‘αŸ… xdp-remote:

ip netns exec remote 
    ip link set dev int xdp object dummy.o

αž₯αž‘αžΌαžœαž“αŸαŸ‡ tcpdump αž”αž„αŸ’αž αžΆαž‰αž–αžΈαž’αŸ’αžœαžΈαžŠαŸ‚αž›αžšαŸ†αž–αžΉαž„αž‘αž»αž€αŸ–

62:57:8e:70:44:64 > 26:0e:25:37:8f:96, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 13762, offset 0, flags [DF], proto ICMP (1), length 84)
    192.0.2.2 > 192.0.2.1: ICMP echo request, id 46966, seq 1, length 64
62:57:8e:70:44:64 > 26:0e:25:37:8f:96, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 13762, offset 0, flags [DF], proto ICMP (1), length 84)
    192.0.2.2 > 192.0.2.1: ICMP echo request, id 46966, seq 1, length 64

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž˜αžΆαž“αžαŸ‚ ARPs αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž αžΆαž‰αž‡αŸ†αž“αž½αžŸαžœαž·αž‰ αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαžŠαž€αžαž˜αŸ’αžšαž„αž…αŸαž‰ (αžœαžΆαž€αžΎαžαž‘αžΎαž„ sudo ./stand detach), αžαŸ„αŸ‡β€‹αž‘αŸ… pingαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž€αŸ†αžŽαžαŸ‹αžαž˜αŸ’αžšαž„ αž αžΎαž™αž–αŸ’αž™αžΆαž™αžΆαž˜αž˜αŸ’αžαž„αž‘αŸ€αžαŸ” αž”αž‰αŸ’αž αžΆαž‚αžΊαžαžΆαžαž˜αŸ’αžšαž„ XDP_TX αž˜αžΆαž“αžŸαž»αž–αž›αž—αžΆαž–αž‘αžΆαŸ†αž„αž“αŸ…αž›αžΎ ARP αž“αž·αž„αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž‡αž„αŸ‹
αž…αž“αŸ’αž›αŸ„αŸ‡αžˆαŸ’αž˜αŸ„αŸ‡ xdp-test αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžŠαžΎαž˜αŸ’αž”αžΈ "αž”αŸ†αž—αŸ’αž›αŸαž…" αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“ MAC 192.0.2.1 αžœαžΆαž“αžΉαž„αž˜αž·αž“αž’αžΆαž…αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™ IP αž“αŸαŸ‡αž”αžΆαž“αž‘αŸαŸ”

αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž”αž‰αŸ’αž αžΆ

αž…αžΌαžšαž”αž“αŸ’αžαž‘αŸ…αž€αž·αž…αŸ’αž…αž€αžΆαžšαžŠαŸ‚αž›αž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αŸ– αžŸαžšαžŸαŸαžšαž™αž“αŸ’αžαž€αžΆαžšαžαžΌαž‚αžΈ SYN αž“αŸ…αž›αžΎ XDP αŸ”

αž‘αžΉαž€αž‡αŸ†αž“αž“αŸ‹ SYN αž“αŸ…αžαŸ‚αž‡αžΆαž€αžΆαžšαžœαžΆαž™αž”αŸ’αžšαž αžΆαžš DDoS αžŠαŸαž–αŸαž‰αž“αž·αž™αž˜ αžŠαŸ‚αž›αžαŸ’αž›αžΉαž˜αžŸαžΆαžšαž˜αžΆαž“αžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸ” αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž‘αžΎαž„ (αž€αžΆαžšαž…αžΆαž”αŸ‹αžŠαŸƒ TCP) αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž‘αž‘αž½αž›αž”αžΆαž“ SYN αž”αŸ‚αž„αž…αŸ‚αž€αž’αž“αž’αžΆαž“αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αž“αžΆαž–αŸαž›αž’αž“αžΆαž‚αž αž†αŸ’αž›αžΎαž™αžαž”αž‡αžΆαž˜αž½αž™αž€αž‰αŸ’αž…αž”αŸ‹ SYNACK αž αžΎαž™αžšαž„αŸ‹αž…αžΆαŸ† ACK αŸ” αž’αŸ’αž“αž€αžœαžΆαž™αž”αŸ’αžšαž αžΆαžšαž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž•αŸ’αž‰αžΎαž€αž‰αŸ’αž…αž”αŸ‹ SYN αžšαžΆαž”αŸ‹αž–αžΆαž“αŸ‹αž€αŸ’αž“αž»αž„αž˜αž½αž™αžœαž·αž“αžΆαž‘αžΈαž–αžΈαž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αž€αŸ’αž›αŸ‚αž„αž€αŸ’αž›αžΆαž™αž–αžΈαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αžΈαž˜αž½αž™αŸ—αž“αŸ…αž€αŸ’αž“αž»αž„ botnet αžŠαŸ‚αž›αž˜αžΆαž“αž€αž˜αŸ’αž›αžΆαŸ†αž„αž…αŸ’αžšαžΎαž“αž–αžΆαž“αŸ‹αŸ” αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αžαŸ†αž±αŸ’αž™αž”αŸ‚αž„αž…αŸ‚αž€αž’αž“αž’αžΆαž“αž—αŸ’αž›αžΆαž˜αŸ—αž“αŸ…αž–αŸαž›αž€αžΆαžšαž˜αž€αžŠαž›αŸ‹αž“αŸƒαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž”αž‰αŸ’αž…αŸαž‰αž–αž½αž€αžœαžΆαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž’αžŸαŸ‹αž–αŸαž›αž…αŸ’αžšαžΎαž“αž‡αžΆαž›αž‘αŸ’αž’αž•αž› αž’αž„αŸ’αž‚αž…αž„αž…αžΆαŸ† αž¬αžŠαŸ‚αž“αž€αŸ†αžŽαžαŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αžŸαŸ‹ αž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αžαŸ’αž˜αžΈαž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‘αž‘αž½αž›αž™αž€ αž αžΎαž™αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αž“αŸαŸ‡αž˜αž·αž“αž’αžΆαž…αž”αŸ’αžšαžΎαž”αžΆαž“αž‘αŸαŸ”

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž˜αž·αž“αž”αŸ‚αž„αž…αŸ‚αž€αž’αž“αž’αžΆαž“αžŠαŸ„αž™αž•αŸ’αž’αŸ‚αž€αž›αžΎαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ SYN αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž†αŸ’αž›αžΎαž™αžαž”αž‡αžΆαž˜αž½αž™αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ SYNACK αž“αŸ„αŸ‡ αžαžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž’αžΆαž…αž™αž›αŸ‹αžŠαŸ„αž™αžšαž”αŸ€αž”αžŽαžΆαžαžΆαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ ACK αžŠαŸ‚αž›αž”αžΆαž“αž˜αž€αžŠαž›αŸ‹αž“αŸ…αž–αŸαž›αž€αŸ’αžšαŸ„αž™αžŸαŸ†αžŠαŸ…αž›αžΎαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ SYN αžŠαŸ‚αž›αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž€αŸ’αžŸαžΆαž‘αž»αž€? αž™αŸ‰αžΆαž„αžŽαžΆαž˜αž·αž‰ αž’αŸ’αž“αž€αžœαžΆαž™αž”αŸ’αžšαž αžΆαžšαž€αŸαž’αžΆαž…αž”αž„αŸ’αž€αžΎαž ACKs αž€αŸ’αž›αŸ‚αž„αž€αŸ’αž›αžΆαž™αž•αž„αžŠαŸ‚αžšαŸ” αž…αŸ†αž“αž»αž…αž“αŸƒαžαžΌαž‚αžΈ SYN αž‚αžΊαž€αžΆαžšαž’αŸŠαž·αž“αž€αžΌαžŠαžœαžΆαž…αžΌαž› seqnum αž”αŸ‰αžΆαžšαŸ‰αžΆαž˜αŸ‰αŸ‚αžαŸ’αžšαž“αŸƒαž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αž‡αžΆ hash αž“αŸƒαž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“ αž…αŸ’αžšαž€ αž“αž·αž„αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž’αŸ†αž”αž·αž›αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎ ACK αž’αžΆαž…αž˜αž€αžŠαž›αŸ‹αž˜αž»αž“αž–αŸαž›αž’αŸ†αž”αž·αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžš αž’αŸ’αž“αž€αž’αžΆαž…αž‚αžŽαž“αžΆ hash αž˜αŸ’αžαž„αž‘αŸ€αž αž αžΎαž™αž”αŸ’αžšαŸ€αž”αž’αŸ€αž”αžœαžΆαž‡αžΆαž˜αž½αž™ acknum. αž€αŸ’αž›αŸ‚αž„αž”αž“αŸ’αž›αŸ† acknum αž’αŸ’αž“αž€αžœαžΆαž™αž”αŸ’αžšαž αžΆαžšαž˜αž·αž“αž’αžΆαž…αž‘αŸ αž–αŸ’αžšαŸ„αŸ‡αž’αŸ†αž”αž·αž›αžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›αž’αžΆαžαŸŒαž€αŸ†αž”αžΆαŸ†αž„ αž αžΎαž™αž“αžΉαž„αž˜αž·αž“αž˜αžΆαž“αž–αŸαž›αžœαŸαž›αžΆαžŠαžΎαž˜αŸ’αž”αžΈαžαž˜αŸ’αžšαŸ€αž”αžœαžΆαž‘αŸ αžŠαŸ„αž™αžŸαžΆαžšαž†αžΆαž“αŸ‚αž›αž˜αžΆαž“αž€αŸ†αžŽαžαŸ‹αŸ”

αžαžΌαž‚αžΈ SYN αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαž‡αžΆαž™αžΌαžšαž˜αž€αž αžΎαž™αž“αŸ…αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž›αž›αžΈαž“αž»αž… αž αžΎαž™αžαŸ‚αž˜αž‘αžΆαŸ†αž„αž’αžΆαž…αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž· αž”αŸ’αžšαžŸαž·αž“αž”αžΎ SYNs αž˜αž€αžŠαž›αŸ‹αž›αžΏαž“αž–αŸαž€ αž“αž·αž„αž˜αžΆαž“αž‘αŸ†αž αŸ†αž’αŸ†αŸ”

αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž’αž”αŸ‹αžšαŸ†αž’αŸ†αž–αžΈαž€αžΆαžšαž…αžΆαž”αŸ‹αžŠαŸƒ TCP

TCP αž•αŸ’αžαž›αŸ‹αž“αžΌαžœαž€αžΆαžšαž”αž‰αŸ’αž‡αžΌαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‡αžΆαžŸαŸ’αž‘αŸ’αžšαžΈαž˜αž“αŸƒαž”αŸƒ αž§αž‘αžΆαž αžšαžŽαŸ αžŸαŸ†αžŽαžΎ HTTP αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αžαžΆαž˜ TCP αŸ” αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž‡αžΆαž”αŸ†αžŽαŸ‚αž€αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž‰αŸ’αž…αž”αŸ‹αŸ” αž€αž‰αŸ’αž…αž”αŸ‹ TCP αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž˜αžΆαž“αž‘αž„αŸ‹αž‘αžΌαž‡αžΈαžαž› αž“αž·αž„αž›αŸαžαž›αŸ†αžŠαžΆαž”αŸ‹ 32 αž”αŸŠαžΈαžαŸ–

  • αž€αžΆαžšαžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›αž‚αŸ’αž“αžΆαž“αŸƒαž‘αž„αŸ‹αž€αŸ†αžŽαžαŸ‹αžαž½αž“αžΆαž‘αžΈαž“αŸƒαž€αž‰αŸ’αž…αž”αŸ‹αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αž˜αž½αž™αŸ” αž‘αž„αŸ‹ SYN αž”αž„αŸ’αž αžΆαž‰αžαžΆαž“αŸαŸ‡αž‚αžΊαž‡αžΆαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αžŠαŸ†αž”αžΌαž„αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž•αŸ’αž‰αžΎαž“αŸ…αž›αžΎαž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αŸ” αž‘αž„αŸ‹ ACK αž˜αžΆαž“αž“αŸαž™αžαžΆαž’αŸ’αž“αž€αž•αŸ’αž‰αžΎαž”αžΆαž“αž‘αž‘αž½αž›αž‘αž·αž“αŸ’αž“αž“αŸαž™αžαž—αŸ’αž‡αžΆαž”αŸ‹αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžšαž αžΌαžαžŠαž›αŸ‹αž”αŸƒ acknum. αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž’αžΆαž…αž˜αžΆαž“αž‘αž„αŸ‹αž‡αžΆαž…αŸ’αžšαžΎαž“ αž αžΎαž™αžαŸ’αžšαžΌαžœαž”αžΆαž“αž αŸ…αžŠαŸ„αž™αž€αžΆαžšαžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›αž‚αŸ’αž“αžΆαžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸ αž§αž‘αžΆαž αžšαžŽαŸ αž€αž‰αŸ’αž…αž”αŸ‹ SYNACK αŸ”

  • αž›αŸαžαž›αŸ†αžŠαžΆαž”αŸ‹ (seqnum) αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž’αž»αž αŸ’αžœαžŸαž·αžαž€αŸ’αž“αž»αž„αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž”αŸƒαžŠαŸ†αž”αžΌαž„αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž€αŸ’αž“αž»αž„αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž“αŸαŸ‡αŸ” αž§αž‘αžΆαž αžšαžŽαŸ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αžŠαŸ†αž”αžΌαž„αžŠαŸ‚αž›αž˜αžΆαž“ X αž”αŸƒαž“αŸƒαž‘αž·αž“αŸ’αž“αž“αŸαž™ αž›αŸαžαž“αŸαŸ‡αž‚αžΊαž‡αžΆ N αž“αŸ„αŸ‡αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž‰αŸ’αž…αž”αŸ‹αž”αž“αŸ’αž‘αžΆαž”αŸ‹αžŠαŸ‚αž›αž˜αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžαŸ’αž˜αžΈαžœαžΆαž“αžΉαž„αž‡αžΆ N + X αŸ” αž“αŸ…αžŠαŸ†αžŽαžΆαž€αŸ‹αž€αžΆαž›αžŠαŸ†αž”αžΌαž„αž“αŸƒαž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹ αž—αžΆαž‚αžΈαž“αžΈαž˜αž½αž™αŸ—αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž›αŸαžαž“αŸαŸ‡αžŠαŸ„αž™αž…αŸƒαžŠαž“αŸ’αž™αŸ”

  • αž›αŸαžαž€αžΆαžšαž‘αž‘αž½αž›αžŸαŸ’αž‚αžΆαž›αŸ‹ (acknum) - αž’αž»αž αŸ’αžœαžŸαž·αžαžŠαžΌαž…αž‚αŸ’αž“αžΆαž“αžΉαž„ seqnum αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžœαžΆαž˜αž·αž“αž€αŸ†αžŽαžαŸ‹αž…αŸ†αž“αž½αž“αž”αŸƒαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž…αŸ†αž“αž½αž“αž”αŸƒαžŠαŸ†αž”αžΌαž„αž–αžΈαž’αŸ’αž“αž€αž‘αž‘αž½αž›αžŠαŸ‚αž›αž’αŸ’αž“αž€αž•αŸ’αž‰αžΎαž˜αž·αž“αž”αžΆαž“αžƒαžΎαž‰αŸ”

αž“αŸ…αžŠαžΎαž˜αžŠαŸ†αž”αžΌαž„αž“αŸƒαž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αž—αžΆαž‚αžΈαžαŸ’αžšαžΌαžœαžαŸ‚αž™αž›αŸ‹αž–αŸ’αžšαž˜ seqnum ΠΈ acknum. αž’αžαž·αžαž·αž‡αž“αž•αŸ’αž‰αžΎαž€αž‰αŸ’αž…αž”αŸ‹ SYN αž‡αžΆαž˜αž½αž™αžœαžΆαŸ” seqnum = X. αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž†αŸ’αž›αžΎαž™αžαž”αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αž‰αŸ’αž…αž”αŸ‹ SYNACK αžŠαŸ‚αž›αžœαžΆαž€αžαŸ‹αžαŸ’αžšαžΆαžšαž”αžŸαŸ‹αžœαžΆαŸ” seqnum = Y αž“αž·αž„αž›αžΆαžαžαŸ’αžšαžŠαžΆαž„ acknum = X + 1. αž’αžαž·αžαž·αž‡αž“αž†αŸ’αž›αžΎαž™αžαž”αž‘αŸ…αž“αžΉαž„ SYNACK αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ ACK αžŠαŸ‚αž›αž‡αžΆαž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž› seqnum = X + 1, acknum = Y + 1. αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž“αŸαŸ‡ αž€αžΆαžšαž•αŸ’αž‘αŸαžšαž‘αž·αž“αŸ’αž“αž“αŸαž™αž–αž·αžαž”αŸ’αžšαžΆαž€αžŠαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αŸ”

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž˜αž·αžαŸ’αžαž—αŸαž€αŸ’αžαž·αž˜αž·αž“αž‘αž‘αž½αž›αžŸαŸ’αž‚αžΆαž›αŸ‹αž€αžΆαžšαž‘αž‘αž½αž›αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž‘αŸ TCP αž“αžΉαž„αž”αž‰αŸ’αž‡αžΌαž“αžœαžΆαž‘αžΎαž„αžœαž·αž‰αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž’αžŸαŸ‹αž–αŸαž›αŸ”

αž αŸαžαž»αž’αŸ’αžœαžΈαž”αžΆαž“αž‡αžΆαžαžΌαž‚αžΈ SYN αž˜αž·αž“αžαŸ‚αž„αžαŸ‚αž”αŸ’αžšαžΎ?

αž‘αžΈαž˜αž½αž™ αž”αŸ’αžšαžŸαž·αž“αž”αžΎ SYNACK ឬ ACK αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αžΆαžαŸ‹αž”αž„αŸ‹ αž’αŸ’αž“αž€αž“αžΉαž„αžαŸ’αžšαžΌαžœαžšαž„αŸ‹αž…αžΆαŸ†αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž‰αžΎαž˜αŸ’αžαž„αž‘αŸ€αž - αž€αžΆαžšαžŠαŸ†αž‘αžΎαž„αž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αž“αžΉαž„αžαž™αž…αž»αŸ‡αŸ” αž‘αžΈαž–αžΈαžšαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž‰αŸ’αž…αž”αŸ‹ SYN - αž αžΎαž™αž˜αžΆαž“αžαŸ‚αž“αŸ…αž€αŸ’αž“αž»αž„αžœαžΆαž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡! - αž‡αž˜αŸ’αžšαžΎαžŸαž˜αž½αž™αž…αŸ†αž“αž½αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“ αžŠαŸ‚αž›αž”αŸ‰αŸ‡αž–αžΆαž›αŸ‹αžŠαž›αŸ‹αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αžαž“αŸƒαž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αŸ” αžŠαŸ„αž™αž˜αž·αž“αž…αžΆαŸ†αž€αž‰αŸ’αž…αž”αŸ‹ SYN αž…αžΌαž›αž‘αŸ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž˜αž·αž“αž’αžΎαž–αžΎαž‡αž˜αŸ’αžšαžΎαžŸαž‘αžΆαŸ†αž„αž“αŸαŸ‡αž‘αŸ αž’αžαž·αžαž·αž‡αž“αž“αžΉαž„αž˜αž·αž“αž•αŸ’αž‰αžΎαž–αž½αž€αžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž‰αŸ’αž…αž”αŸ‹αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž‘αŸαŸ” TCP αž’αžΆαž…αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž“αŸαŸ‡ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž™αŸ‰αžΆαž„αž αŸ„αž…αžŽαžΆαžŸαŸ‹αž“αŸ…αžŠαŸ†αžŽαžΆαž€αŸ‹αž€αžΆαž›αžŠαŸ†αž”αžΌαž„ αž‚αž»αžŽαž—αžΆαž–αž“αŸƒαž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αž“αžΉαž„αžαž™αž…αž»αŸ‡αŸ”

αž“αŸ…αž€αŸ’αž“αž»αž„αž›αž€αŸ’αžαžαžŽαŸ’αžŒαž“αŸƒαž€αž‰αŸ’αž…αž”αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ XDP αžαŸ’αžšαžΌαžœαž’αŸ’αžœαžΎαžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜:

  • αž†αŸ’αž›αžΎαž™αžαž”αž‘αŸ… SYN αž‡αžΆαž˜αž½αž™ SYNACK αž‡αžΆαž˜αž½αž™αžαžΌαž‚αžΈ;
  • αž†αŸ’αž›αžΎαž™αžαž”αž‘αŸ…αž“αžΉαž„ ACK αž‡αžΆαž˜αž½αž™ RST (αž•αŸ’αžαžΆαž…αŸ‹);
  • αž”αŸ„αŸ‡αž…αŸ„αž›αž€αž‰αŸ’αž…αž”αŸ‹αžŠαŸ‚αž›αž“αŸ…αžŸαž›αŸ‹αŸ”

Pseudocode αž“αŸƒ algorithm αžšαž½αž˜αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž‰αŸ‚αž€αž€αž‰αŸ’αž…αž”αŸ‹αŸ–

Если это Π½Π΅ Ethernet,
    ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚.
Если это Π½Π΅ IPv4,
    ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚.
Если адрСс Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π½Ρ‹Ρ…,               (*)
        ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΡ‚ΡŒ счСтчик ΠΎΡΡ‚Π°Π²ΡˆΠΈΡ…ΡΡ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΎΠΊ,
        ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚.
Если это Π½Π΅ TCP,
    ΡΠ±Ρ€ΠΎΡΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚.     (**)
Если это SYN,
    ΠΎΡ‚Π²Π΅Ρ‚ΠΈΡ‚ΡŒ SYN-ACK с cookie.
Если это ACK,
    Ссли Π² acknum Π»Π΅ΠΆΠΈΡ‚ Π½Π΅ cookie,
        ΡΠ±Ρ€ΠΎΡΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚.
    ЗанСсти Π² Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ адрСс с N ΠΎΡΡ‚Π°Π²ΡˆΠΈΡ…ΡΡ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΎΠΊ.    (*)
    ΠžΡ‚Π²Π΅Ρ‚ΠΈΡ‚ΡŒ RST.   (**)
Π’ ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… случаях ΡΠ±Ρ€ΠΎΡΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚.

αž˜αž½αž™αŸ” (*) αž…αŸ†αžŽαž»αž…αžŠαŸ‚αž›αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž€αžΆαžšαžŠαžΎαž˜αŸ’αž”αžΈαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžŸαŸ’αžαžΆαž“αž—αžΆαž–αž“αŸƒαž”αŸ’αžšαž–αŸαž“αŸ’αž’αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαž˜αŸ’αž‚αžΆαž›αŸ‹ - αž“αŸ…αžŠαŸ†αžŽαžΆαž€αŸ‹αž€αžΆαž›αžŠαŸ†αž”αžΌαž„αž’αŸ’αž“αž€αž’αžΆαž…αž’αŸ’αžœαžΎαž”αžΆαž“αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž–αž½αž€αžœαžΆαžŠαŸ„αž™αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαž…αžΆαž”αŸ‹αžŠαŸƒ TCP αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαžαžΌαž‚αžΈ SYN αž‡αžΆ seqnum αŸ”

αž“αŸ…β€‹αž“αžΉαž„β€‹αž€αž“αŸ’αž›αŸ‚αž„ (**)αžαžŽαŸˆαž–αŸαž›αžŠαŸ‚αž›αž™αžΎαž„αž˜αž·αž“αž˜αžΆαž“αžαž» αž™αžΎαž„αž“αžΉαž„αžšαŸ†αž›αž„αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αŸ”

αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαž…αžΆαž”αŸ‹αžŠαŸƒ TCP

αž‰αŸ‚αž€αž€αž‰αŸ’αž…αž”αŸ‹ αž“αž·αž„αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž›αŸαžαž€αžΌαžŠ

αž™αžΎαž„αž“αžΉαž„αžαŸ’αžšαžΌαžœαž€αžΆαžšαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž”αž‹αž˜αž€αžαžΆαž”αžŽαŸ’αžαžΆαž‰αŸ– ធ៊ីសឺរណិត (uapi/linux/if_ether.h), IPv4 (uapi/linux/ip.h) αž“αž·αž„ TCP (uapi/linux/tcp.h) αžαŸ’αž‰αž»αŸ†αž˜αž·αž“αž’αžΆαž…αž—αŸ’αž‡αžΆαž”αŸ‹αž‘αŸ†αž“αžΆαž€αŸ‹αž‘αŸ†αž“αž„αž€αŸ’αžšαŸ„αž™αž”αžΆαž“αž‘αŸ αžŠαŸ„αž™αžŸαžΆαžšαž˜αžΆαž“αž€αŸ†αž αž»αžŸαž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„ atomic64_tαžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž…αž˜αŸ’αž›αž„αž“αž·αž™αž˜αž“αŸαž™αž…αžΆαŸ†αž”αžΆαž…αŸ‹αž‘αŸ…αž€αŸ’αž“αž»αž„αž€αžΌαžŠαŸ”

αž˜αž»αžαž„αžΆαžšαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αž›αž·αž…αž“αŸ…αž€αŸ’αž“αž»αž„ C αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž—αžΆαž–αž’αžΆαž…αž’αžΆαž“αž”αžΆαž“αžαŸ’αžšαžΌαžœαžαŸ‚αžŠαžΆαž€αŸ‹αž”αž‰αŸ’αž…αžΌαž›αž“αŸ…αž…αŸ†αžŽαž»αž…αž“αŸƒαž€αžΆαžšαž αŸ…αž‘αžΌαžšαžŸαž–αŸ’αž‘ αž–αŸ’αžšαŸ„αŸ‡αžαžΆαž’αŸ’αž“αž€αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹ eBPF αž“αŸ…αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž›αž αžΆαž˜αžƒαžΆαžαŸ‹αž€αžΆαžšαžαžΆαž˜αžŠαžΆαž“αžαŸ’αžšαž›αž”αŸ‹αž˜αž€αžœαž·αž‰ αž–αŸ„αž›αž‚αžΊαžαžΆαž˜αž–αž·αž αžšαž„αŸ’αžœαž·αž›αž‡αž»αŸ† αž“αž·αž„αž€αžΆαžšαž αŸ…αž˜αž»αžαž„αžΆαžšαŸ”

#define INTERNAL static __attribute__((always_inline))

αž˜αŸ‰αžΆαž€αŸ’αžšαžΌ LOG() αž”αž·αž‘αž€αžΆαžšαž”αŸ„αŸ‡αž–αž»αž˜αŸ’αž–αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž…αŸαž‰αž•αŸ’αžŸαžΆαž™αŸ”

αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‚αžΊαž‡αžΆαž§αž”αž€αžšαžŽαŸαž”αž‰αŸ’αž‡αžΌαž“αž“αŸƒαž˜αž»αžαž„αžΆαžšαŸ” αž“αžΈαž˜αž½αž™αŸ—αž‘αž‘αž½αž›αž”αžΆαž“αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αžŠαŸ‚αž›αž”αž‹αž˜αž€αžαžΆαž€αž˜αŸ’αžšαž·αžαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž‚αŸ’αž“αžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αž›αž·αž… αž§αž‘αžΆαž αžšαžŽαŸ process_ether() αžšαŸ†αž–αžΉαž„αžαžΆαžœαžΆαž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ†αž–αŸαž‰ ether. αžŠαŸ„αž™αž•αŸ’αž’αŸ‚αž€αž›αžΎαž›αž‘αŸ’αž’αž•αž›αž“αŸƒαž€αžΆαžšαžœαž·αž—αžΆαž‚αžœαžΆαž› αž˜αž»αžαž„αžΆαžšαž’αžΆαž…αž”αž‰αŸ’αž‡αžΌαž“αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž‘αŸ…αž€αž˜αŸ’αžšαž·αžαžαŸ’αž–αžŸαŸ‹αŸ” αž›αž‘αŸ’αž’αž•αž›αž“αŸƒαž˜αž»αžαž„αžΆαžšαž‚αžΊαžŸαž€αž˜αŸ’αž˜αž—αžΆαž– XDP αŸ” αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž–αŸαž›αž“αŸαŸ‡ αž’αŸ’αž“αž€αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™ SYN αž“αž·αž„ ACK αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αŸ”

struct Packet {
    struct xdp_md* ctx;

    struct ethhdr* ether;
    struct iphdr* ip;
    struct tcphdr* tcp;
};

INTERNAL int process_tcp_syn(struct Packet* packet) { return XDP_PASS; }
INTERNAL int process_tcp_ack(struct Packet* packet) { return XDP_PASS; }
INTERNAL int process_tcp(struct Packet* packet) { ... }
INTERNAL int process_ip(struct Packet* packet) { ... }

INTERNAL int
process_ether(struct Packet* packet) {
    struct ethhdr* ether = packet->ether;

    LOG("Ether(proto=0x%x)", bpf_ntohs(ether->h_proto));

    if (ether->h_proto != bpf_ntohs(ETH_P_IP)) {
        return XDP_PASS;
    }

    // B
    struct iphdr* ip = (struct iphdr*)(ether + 1);
    if ((void*)(ip + 1) > (void*)packet->ctx->data_end) {
        return XDP_DROP; /* malformed packet */
    }

    packet->ip = ip;
    return process_ip(packet);
}

SEC("prog")
int xdp_main(struct xdp_md* ctx) {
    struct Packet packet;
    packet.ctx = ctx;

    // A
    struct ethhdr* ether = (struct ethhdr*)(void*)ctx->data;
    if ((void*)(ether + 1) > (void*)ctx->data_end) {
        return XDP_PASS;
    }

    packet.ether = ether;
    return process_ether(&packet);
}

αžαŸ’αž‰αž»αŸ†αž‘αžΆαž€αŸ‹αž‘αžΆαž‰αž€αžΆαžšαž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž…αŸ†αž–αŸ„αŸ‡αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αžŠαŸ‚αž›αž”αžΆαž“αžŸαž˜αŸ’αž‚αžΆαž›αŸ‹ A αž“αž·αž„ BαŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž”αž‰αŸ’αž…αŸαž‰αž˜αžαž· A αž“αŸ„αŸ‡αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž“αžΉαž„αž”αž„αŸ’αž€αžΎαž αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αžΉαž„αž˜αžΆαž“αž€αŸ†αž αž»αžŸαž€αŸ’αž“αž»αž„αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž“αŸ…αž–αŸαž›αž•αŸ’αž‘αž»αž€αŸ–

Verifier analysis:

<...>
11: (7b) *(u64 *)(r10 -48) = r1
12: (71) r3 = *(u8 *)(r7 +13)
invalid access to packet, off=13 size=1, R7(id=0,off=0,r=0)
R7 offset is outside of the packet
processed 11 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

Error fetching program/map!

αžαŸ’αžŸαŸ‚αž’αž€αŸ’αžŸαžš invalid access to packet, off=13 size=1, R7(id=0,off=0,r=0)αŸ– αž˜αžΆαž“αž•αŸ’αž›αžΌαžœαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž”αŸƒαž‘αžΈαžŠαž”αŸ‹αž”αžΈαž–αžΈαž€αžΆαžšαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž“αŸƒαžŸαžαž·αž”αžŽαŸ’αžŠαŸ„αŸ‡αž’αžΆαžŸαž“αŸ’αž“αž“αŸ…αžαžΆαž„αž€αŸ’αžšαŸ…αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αŸ” αžœαžΆαž–αž·αž”αžΆαž€αž€αŸ’αž“αž»αž„αž€αžΆαžšαž™αž›αŸ‹αž–αžΈαž€αžΆαžšαžšαžΆαž™αž”αž‰αŸ’αž‡αžΈαž˜αž½αž™αžŽαžΆαžŠαŸ‚αž›αž™αžΎαž„αž€αŸ†αž–αž»αž„αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž˜αžΆαž“αž›αŸαžαžŽαŸ‚αž“αžΆαŸ† (12) αž“αž·αž„αž§αž”αž€αžšαžŽαŸαž”αŸ†αž”αŸ‚αž€αžŠαŸ‚αž›αž”αž„αŸ’αž αžΆαž‰αž”αž“αŸ’αž‘αžΆαžαŸ‹αž“αŸƒαž€αžΌαžŠαž”αŸ’αžšαž—αž–αŸ–

llvm-objdump -S xdp_filter.o | less

αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž“αŸαŸ‡αžœαžΆαž…αž„αŸ’αž’αž»αž›αž‘αŸ…αž”αž“αŸ’αž‘αžΆαžαŸ‹

LOG("Ether(proto=0x%x)", bpf_ntohs(ether->h_proto));

αžŠαŸ‚αž›αž’αŸ’αžœαžΎαž±αŸ’αž™αžœαžΆαž…αŸ’αž”αžΆαžŸαŸ‹αžαžΆαž”αž‰αŸ’αž αžΆαž‚αžΊ ether. αžœαžΆαž“αžΉαž„αžαŸ‚αž„αžαŸ‚αžŠαžΌαž…αž“αŸαŸ‡αŸ”

αž†αŸ’αž›αžΎαž™αžαž”αž‘αŸ… SYN

αž‚αŸ„αž›αžŠαŸ…αž“αŸ…αžŠαŸ†αžŽαžΆαž€αŸ‹αž€αžΆαž›αž“αŸαŸ‡αž‚αžΊαžŠαžΎαž˜αŸ’αž”αžΈαž”αž„αŸ’αž€αžΎαžαž€αž‰αŸ’αž…αž”αŸ‹ SYNACK αžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœαž‡αžΆαž˜αž½αž™αž“αžΉαž„αžαŸαžšαž˜αž½αž™αŸ” seqnumαžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‡αŸ†αž“αž½αžŸαž“αŸ…αž–αŸαž›αž’αž“αžΆαž‚αžαžŠαŸ„αž™αžαžΌαž‚αžΈ SYN αŸ” αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž€αžΎαžαž‘αžΎαž„αž“αŸ…αž€αŸ’αž“αž»αž„ process_tcp_syn() αž“αž·αž„αžαŸ†αž”αž“αŸ‹αž‡αž»αŸ†αžœαž·αž‰αŸ”

αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž€αž‰αŸ’αž…αž”αŸ‹

αž…αž˜αŸ’αž›αŸ‚αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹αž αžΎαž™ αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž”αž“αŸ’αž‘αžΆαžαŸ‹αžŠαŸαž‚αž½αžšαž±αŸ’αž™αž€αžαŸ‹αžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž”αŸ†αž•αž»αž αž¬αž‡αžΆαž€αžΆαžšαž’αžαŸ’αžαžΆαž’αž·αž”αŸ’αž”αžΆαž™αž…αŸ†αž–αŸ„αŸ‡αžœαžΆαŸ–

/* Required to verify checksum calculation */
const void* data_end = (const void*)ctx->data_end;

αž“αŸ…αž–αŸαž›αžŸαžšαžŸαŸαžšαž€αžΌαžŠαž€αŸ†αžŽαŸ‚αžŠαŸ†αž”αžΌαž„αž“αŸƒ αžαžΊαžŽαŸ‚αž› 5.1 αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹ αžŠαŸ‚αž›αžœαžΆαž˜αžΆαž“αž—αžΆαž–αžαž»αžŸαž‚αŸ’αž“αžΆαžšαžœαžΆαž„ data_end ΠΈ (const void*)ctx->data_end. αž“αŸ…αž–αŸαž›αžŸαžšαžŸαŸαžš αžαžΊαžŽαŸ‚αž› 5.3.1 αž˜αž·αž“αž˜αžΆαž“αž”αž‰αŸ’αž αžΆαž“αŸαŸ‡αž‘αŸαŸ” αžœαžΆαž’αžΆαž…αž‘αŸ…αžšαž½αž…αžŠαŸ‚αž›αžαžΆαž’αŸ’αž“αž€αž…αž„αž€αŸ’αžšαž„αž€αŸ†αž–αž»αž„αž…αžΌαž›αž”αŸ’αžšαžΎαž’αžαŸαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αžαž»αžŸαž–αžΈαžœαžΆαž›αŸ” αžŸαžΈαž›αž’αž˜αŸŒαž“αŸƒαžšαžΏαž„αŸ– αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αžŸαŸ†αž”αž»αž€αž˜αžΆαž“αž‘αŸ†αž αŸ†αž’αŸ† αž€αžΆαžšαž’αŸ’αžœαžΎαž±αŸ’αž™αž€αžΌαžŠαžŸαžΆαž˜αž‰αŸ’αž‰αž’αžΆαž…αž‡αž½αž™αž”αžΆαž“αŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž‚αžΊαž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž”αŸ’αžšαžœαŸ‚αž„αž‡αžΆαž‘αž˜αŸ’αž›αžΆαž”αŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž—αžΆαž–αžšαž»αž„αžšαžΏαž„αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αŸ” ធូ MAX_CSUM_BYTES αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸ”

const u32 ip_len = ip->ihl * 4;
if ((void*)ip + ip_len > data_end) {
    return XDP_DROP; /* malformed packet */
}
if (ip_len > MAX_CSUM_BYTES) {
    return XDP_ABORTED; /* implementation limitation */
}

const u32 tcp_len = tcp->doff * 4;
if ((void*)tcp + tcp_len > (void*)ctx->data_end) {
    return XDP_DROP; /* malformed packet */
}
if (tcp_len > MAX_CSUM_BYTES) {
    return XDP_ABORTED; /* implementation limitation */
}

αž€αžΆαžšαž›αžΆαžαžαŸ’αžšαžŠαžΆαž„αž€αž‰αŸ’αž…αž”αŸ‹

αž”αŸ†αž–αŸαž‰β€‹αž€αŸ’αž“αž»αž„ seqnum ΠΈ acknumαž€αŸ†αžŽαžαŸ‹ ACK (SYN αžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹αžšαž½αž…αž αžΎαž™)αŸ–

const u32 cookie = 42;
tcp->ack_seq = bpf_htonl(bpf_ntohl(tcp->seq) + 1);
tcp->seq = bpf_htonl(cookie);
tcp->ack = 1;

αž”αŸ’αžαžΌαžšαž…αŸ’αžšαž€ TCP αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“ IP αž“αž·αž„αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“ MAC αŸ” αž”αžŽαŸ’αžŽαžΆαž›αŸαž™αžŸαŸ’αžαž„αŸ‹αžŠαžΆαžšαž˜αž·αž“αž’αžΆαž…αž…αžΌαž›αž”αŸ’αžšαžΎαž”αžΆαž“αž–αžΈαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ XDP αžŠαžΌαž…αŸ’αž“αŸαŸ‡ memcpy() - αž˜αŸ‰αžΆαž€αŸ’αžšαžΌαžŠαŸ‚αž›αž›αžΆαž€αŸ‹αžαžΆαž„αž€αŸ’αž“αž»αž„ Clang αŸ”

const u16 temp_port = tcp->source;
tcp->source = tcp->dest;
tcp->dest = temp_port;

const u32 temp_ip = ip->saddr;
ip->saddr = ip->daddr;
ip->daddr = temp_ip;

struct ethhdr temp_ether = *ether;
memcpy(ether->h_dest, temp_ether.h_source, ETH_ALEN);
memcpy(ether->h_source, temp_ether.h_dest, ETH_ALEN);

αž€αžΆαžšαž‚αžŽαž“αžΆαž‘αžΎαž„αžœαž·αž‰αž“αŸƒαž˜αžΌαž›αž”αŸ’αž”αž‘αžΆαž“αž”αŸαžαŸ’αžš

αž€αžΆαžšαž–αž·αž“αž·αžαŸ’αž™ IPv4 αž“αž·αž„ TCP αž‘αžΆαž˜αž‘αžΆαžšαž€αžΆαžšαž”αž“αŸ’αžαŸ‚αž˜αž–αžΆαž€αŸ’αž™ 16 αž”αŸŠαžΈαžαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž”αž‹αž˜αž€αžαžΆ αž αžΎαž™αž‘αŸ†αž αŸ†αž“αŸƒαž”αž‹αž˜αž€αžαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαžšαžŸαŸαžšαž‘αŸ…αž€αŸ’αž“αž»αž„αž–αž½αž€αžœαžΆ αž–αŸ„αž›αž‚αžΊαž˜αž·αž“αžŸαŸ’αž‚αžΆαž›αŸ‹αž“αŸ…αž–αŸαž›αž…αž„αž€αŸ’αžšαž„αŸ” αž“αŸαŸ‡β€‹αž‡αžΆβ€‹αž”αž‰αŸ’αž αžΆβ€‹αž–αŸ’αžšαŸ„αŸ‡β€‹αž’αŸ’αž“αž€β€‹αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹β€‹αž“αžΉαž„β€‹αž˜αž·αž“β€‹αžšαŸ†αž›αž„β€‹αžšαž„αŸ’αžœαž·αž›αž‡αž»αŸ†β€‹αž’αž˜αŸ’αž˜αžαžΆβ€‹αž‘αŸ…β€‹αž’αžαŸαžšβ€‹αž–αŸ’αžšαŸ†αžŠαŸ‚αž“αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž‘αŸ†αž αŸ†αž“αŸƒαž”αž‹αž˜αž€αžαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹: αžšαž αžΌαžαžŠαž›αŸ‹ 64 αž”αŸƒαž“αžΈαž˜αž½αž™αŸ—αŸ” αž’αŸ’αž“αž€αž’αžΆαž…αž”αž„αŸ’αž€αžΎαžαžšαž„αŸ’αžœαž·αž›αž‡αž»αŸ†αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž…αŸ†αž“αž½αž“αžαŸαžšαž“αŸƒαž€αžΆαžšαž’αŸ’αžœαžΎαžŠαžŠαŸ‚αž›αŸ— αžŠαŸ‚αž›αž’αžΆαž…αž”αž‰αŸ’αž…αž”αŸ‹αž˜αž»αž“αŸ”

αžαŸ’αž‰αž»αŸ†αž€αžαŸ‹αžŸαŸ†αž‚αžΆαž›αŸ‹αžαžΆαž˜αžΆαž“ RFC 1624 αž’αŸ†αž–αžΈαžšαž”αŸ€αž”αž‚αžŽαž“αžΆαž˜αžΌαž›αž”αŸ’αž”αž‘αžΆαž“αž”αŸαžαŸ’αžšαžŠαŸ„αž™αž•αŸ’αž“αŸ‚αž€ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž˜αžΆαž“αžαŸ‚αž–αžΆαž€αŸ’αž™αžαŸαžšαž“αŸƒαž€αž‰αŸ’αž…αž”αŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαŸ” αž‘αŸ„αŸ‡αž‡αžΆαž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžαŸ’αžšαž“αŸαŸ‡αž˜αž·αž“αž˜αŸ‚αž“αž‡αžΆαžŸαž€αž›αž‘αŸ αž αžΎαž™αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž“αžΉαž„αž€αžΆαž“αŸ‹αžαŸ‚αž›αŸ†αž”αžΆαž€αž€αŸ’αž“αž»αž„αž€αžΆαžšαžαŸ‚αžšαž€αŸ’αžŸαžΆαŸ”

αž˜αž»αžαž„αžΆαžšαž‚αžŽαž“αžΆ ChecksumαŸ–

#define MAX_CSUM_WORDS 32
#define MAX_CSUM_BYTES (MAX_CSUM_WORDS * 2)

INTERNAL u32
sum16(const void* data, u32 size, const void* data_end) {
    u32 s = 0;
#pragma unroll
    for (u32 i = 0; i < MAX_CSUM_WORDS; i++) {
        if (2*i >= size) {
            return s; /* normal exit */
        }
        if (data + 2*i + 1 + 1 > data_end) {
            return 0; /* should be unreachable */
        }
        s += ((const u16*)data)[i];
    }
    return s;
}

αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆ size αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αžŠαŸ„αž™αž›αŸαžαž€αžΌαžŠαž αŸ…αž‘αžΌαžšαžŸαž–αŸ’αž‘ αž›αž€αŸ’αžαžαžŽαŸ’αžŒαž…αŸαž‰αž‘αžΈαž–αžΈαžšαž‚αžΊαž…αžΆαŸ†αž”αžΆαž…αŸ‹αžŠαžΎαž˜αŸ’αž”αžΈαž±αŸ’αž™αž’αŸ’αž“αž€αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž’αžΆαž…αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž–αžΈαž€αžΆαžšαž”αž‰αŸ’αž…αž”αŸ‹αž“αŸƒαžšαž„αŸ’αžœαž·αž›αž‡αž»αŸ†αŸ”

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž–αžΆαž€αŸ’αž™ 32 αž”αŸŠαžΈαž αž€αŸ†αžŽαŸ‚αžŠαŸαžŸαžΆαž˜αž‰αŸ’αž‰αž˜αž½αž™αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαŸ–

INTERNAL u32
sum16_32(u32 v) {
    return (v >> 16) + (v & 0xffff);
}

αžαžΆαž˜αž–αž·αžαž€αžΆαžšαž‚αžŽαž“αžΆαž‘αžΎαž„αžœαž·αž‰αž“αžΌαžœαž˜αžΌαž›αž”αŸ’αž”αž‘αžΆαž“αž”αŸαžαŸ’αžš αž“αž·αž„αž€αžΆαžšαž”αž‰αŸ’αž‡αžΌαž“αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αžαŸ’αžšαž‘αž”αŸ‹αž˜αž€αžœαž·αž‰αŸ–

ip->check = 0;
ip->check = carry(sum16(ip, ip_len, data_end));

u32 tcp_csum = 0;
tcp_csum += sum16_32(ip->saddr);
tcp_csum += sum16_32(ip->daddr);
tcp_csum += 0x0600;
tcp_csum += tcp_len << 8;
tcp->check = 0;
tcp_csum += sum16(tcp, tcp_len, data_end);
tcp->check = carry(tcp_csum);

return XDP_TX;

αž˜αž»αžαž„αžΆαžš carry() αž”αž„αŸ’αž€αžΎαžαž˜αžΌαž›αž”αŸ’αž”αž‘αžΆαž“αž”αŸαžαŸ’αžšαž–αžΈαž•αž›αž”αžΌαž€ 32 αž”αŸŠαžΈαžαž“αŸƒαž–αžΆαž€αŸ’αž™ 16 αž”αŸŠαžΈαž αž™αŸ„αž„αž‘αŸ…αžαžΆαž˜ RFC 791 αŸ”

αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž€αžΆαžšαž…αžΆαž”αŸ‹αžŠαŸƒ TCP

αžαž˜αŸ’αžšαž„αž”αž„αŸ’αž€αžΎαžαž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αž™αŸ‰αžΆαž„αžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœαž‡αžΆαž˜αž½αž™ netcatαž”αžΆαžαŸ‹ ACK αž…αž»αž„αž€αŸ’αžšαŸ„αž™ αžŠαŸ‚αž›αž›αžΈαž“αž»αž…αž”αžΆαž“αž†αŸ’αž›αžΎαž™αžαž”αž‡αžΆαž˜αž½αž™αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ RST αž…αžΆαž”αŸ‹αžαžΆαŸ†αž„αž–αžΈαž‡αž„αŸ‹αž”αžŽαŸ’αžαžΆαž‰αž˜αž·αž“αž‘αž‘αž½αž›αž”αžΆαž“ SYN - αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ†αž”αŸ’αž›αŸ‚αž„αž‘αŸ…αž‡αžΆ SYNACK αž αžΎαž™αž”αž‰αŸ’αž‡αžΌαž“αž˜αž€αžœαž·αž‰ - αž αžΎαž™αžαžΆαž˜αž‘αžŸαŸ’αžŸαž“αŸˆαžšαž”αžŸαŸ‹ OS αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž”αžΆαž“αž˜αž€αžŠαž›αŸ‹αžŠαŸ‚αž›αž˜αž·αž“αž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„αž€αžΆαžšαž”αžΎαž€ αž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αŸ”

$ sudo ip netns exec xdp-test   nc -nv 192.0.2.1 6666
192.0.2.1 6666: Connection reset by peer

αžœαžΆαž˜αžΆαž“αžŸαžΆαžšαŸˆαžŸαŸ†αžαžΆαž“αŸ‹αžŽαžΆαžŸαŸ‹αž€αŸ’αž“αž»αž„αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž–αŸαž‰αž›αŸαž‰ αž“αž·αž„αžŸαž„αŸ’αž€αŸαž tcpdump αž“αŸ…αž›αžΎ xdp-remote αžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚αž§αž‘αžΆαž αžšαžŽαŸ hping3 αž˜αž·αž“αž†αŸ’αž›αžΎαž™αžαž”αž‘αŸ…αž“αžΉαž„αž˜αžΌαž›αž”αŸ’αž”αž‘αžΆαž“αž”αŸαžαŸ’αžšαž˜αž·αž“αžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœαž‘αŸαŸ”

αžαžΆαž˜αž‘αžŸαŸ’αžŸαž“αŸˆ XDP αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αžαŸ’αž›αž½αž“αžœαžΆαž‚αžΊαž˜αž·αž“αžŸαŸ†αžαžΆαž“αŸ‹αŸ” αž€αŸ’αž”αž½αž“αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž€αžΆαžšαž‚αžŽαž“αžΆαž‚αžΊαž˜αžΆαž“αž›αž€αŸ’αžαžŽαŸˆαž”αž‹αž˜ αž αžΎαž™αž‘αŸ†αž“αž„αž‡αžΆαž„αžΆαž™αžšαž„αž‚αŸ’αžšαŸ„αŸ‡αž…αŸ†αž–αŸ„αŸ‡αž’αŸ’αž“αž€αžœαžΆαž™αž”αŸ’αžšαž αžΆαžšαžŠαŸαž‘αŸ†αž“αžΎαž”αŸ” αž‡αžΆαž§αž‘αžΆαž αžšαžŽαŸ αžαžΊαžŽαŸ‚αž›αž›αžΈαž“αž»αž… αž”αŸ’αžšαžΎαž€αžΌαžŠαž‚αŸ’αžšαžΈαž” SipHash αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαžšαž”αžŸαŸ‹αžœαžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ XDP αž‚αžΊαž αž½αžŸαž–αžΈαžœαž·αžŸαžΆαž›αž—αžΆαž–αž“αŸƒαž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αŸ”

αžŽαŸ‚αž“αžΆαŸ†αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ TODOs αžαŸ’αž˜αžΈαž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„αž‘αŸ†αž“αžΆαž€αŸ‹αž‘αŸ†αž“αž„αžαžΆαž„αž€αŸ’αžšαŸ…αŸ–

  • αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ XDP αž˜αž·αž“αž’αžΆαž…αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž”αžΆαž“αž‘αŸαŸ” cookie_seed (αž•αŸ’αž“αŸ‚αž€αžŸαž˜αŸ’αž„αžΆαžαŸ‹αž“αŸƒαž’αŸ†αž”αž·αž›) αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸαžšαžŸαž€αž› αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž€αžΆαžšαž€αžΆαžšαž•αŸ’αž‘αž»αž€αž“αŸ…αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž› αžαž˜αŸ’αž›αŸƒαžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž‡αžΆαž‘αŸ€αž„αž‘αžΆαžαŸ‹αž–αžΈαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž—αŸ’αž›αžΎαž„αžŠαŸ‚αž›αž’αžΆαž…αž‘αž»αž€αž…αž·αžαŸ’αžαž”αžΆαž“αŸ”

  • αž”αŸ’αžšαžŸαž·αž“αž”αžΎαžαžΌαž‚αžΈ SYN αžαŸ’αžšαžΌαžœαž‚αŸ’αž“αžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ ACK αž’αŸ’αž“αž€αž˜αž·αž“αž…αžΆαŸ†αž”αžΆαž…αŸ‹αž”αŸ„αŸ‡αž–αž»αž˜αŸ’αž–αžŸαžΆαžšαž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαŸ’αžšαžΌαžœαž…αž„αž…αžΆαŸ† IP αžšαž”αžŸαŸ‹αž’αžαž·αžαž·αž‡αž“αžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹ αžŠαžΎαž˜αŸ’αž”αžΈαž”αž“αŸ’αžαž†αŸ’αž›αž„αž€αžΆαžαŸ‹αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž–αžΈαžœαžΆαŸ”

αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž’αžαž·αžαž·αž‡αž“αžŸαŸ’αžšαž”αž…αŸ’αž”αžΆαž”αŸ‹αŸ–

$ sudoip netns exec xdp-test   nc -nv 192.0.2.1 6666
192.0.2.1 6666: Connection reset by peer

αž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αž”αž„αŸ’αž αžΆαž‰αžαžΆαž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž”αžΆαž“αž†αŸ’αž›αž„αž€αžΆαžαŸ‹ (flags=0x2 - αž“αŸαŸ‡αž‚αžΊαž‡αžΆ SYN flags=0x10 αž‚αžΊ ACK)αŸ–

Ether(proto=0x800)
  IP(src=0x20e6e11a dst=0x20e6e11e proto=6)
    TCP(sport=50836 dport=6666 flags=0x2)
Ether(proto=0x800)
  IP(src=0xfe2cb11a dst=0xfe2cb11e proto=6)
    TCP(sport=50836 dport=6666 flags=0x10)
      cookie matches for client 20200c0

αžαžŽαŸˆαž–αŸαž›αžŠαŸ‚αž›αž˜αž·αž“αž˜αžΆαž“αž”αž‰αŸ’αž‡αžΈ IPs αžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹ αžœαžΆαž“αžΉαž„αž˜αž·αž“αž˜αžΆαž“αž€αžΆαžšαž€αžΆαžšαž–αžΆαžšαž–αžΈαž‘αžΉαž€αž‡αŸ†αž“αž“αŸ‹ SYN αžŠαŸ„αž™αžαŸ’αž›αž½αž“αž―αž„αž“αŸ„αŸ‡αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž”αŸ’αžšαžαž·αž€αž˜αŸ’αž˜αž…αŸ†αž–αŸ„αŸ‡αž‘αžΉαž€αž‡αŸ†αž“αž“αŸ‹ ACK αžŠαŸ‚αž›αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžŠαŸ„αž™αž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸ–

sudo ip netns exec xdp-test   hping3 --flood -A -s 1111 -p 2222 192.0.2.1

αž’αžΆαžαž»αž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αŸ–

Ether(proto=0x800)
  IP(src=0x15bd11a dst=0x15bd11e proto=6)
    TCP(sport=3236 dport=2222 flags=0x10)
      cookie mismatch

αžŸαŸαž…αž€αŸ’αžαžΈαžŸαž“αŸ’αž“αž·αžŠαŸ’αž‹αžΆαž“

αž–αŸαž›αžαŸ’αž›αŸ‡ eBPF αž‡αžΆαž‘αžΌαž‘αŸ… αž“αž·αž„αž‡αžΆαž–αž·αžŸαŸαžŸ XDP αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž αžΆαž‰αž‡αžΆαž§αž”αž€αžšαžŽαŸαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž€αž˜αŸ’αžšαž·αžαžαŸ’αž–αžŸαŸ‹αž‡αžΆαž„αž‡αžΆαžœαŸαž‘αž·αž€αžΆαž’αž—αž·αžœαžŒαŸ’αžαž“αŸαŸ” αž‡αžΆαž€αžΆαžšαž–αž·αž XDP αž‚αžΊαž‡αžΆαž§αž”αž€αžšαžŽαŸαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‡αŸ’αžšαŸ€αžαž‡αŸ’αžšαŸ‚αž€αž‡αžΆαž˜αž½αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸƒαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αžŠαŸ„αž™αžαžΊαžŽαŸ‚αž› αž αžΎαž™αž˜αž·αž“αž˜αŸ‚αž“αž‡αžΆαž‡αž˜αŸ’αžšαžΎαžŸαž‡αŸ†αž“αž½αžŸαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‡αž„αŸ‹αžαžΊαžŽαŸ‚αž› αžŠαžΌαž…αž‡αžΆ DPDK αž“αž·αž„αž‡αž˜αŸ’αžšαžΎαžŸαž†αŸ’αž›αž„αžαžΊαžŽαŸ‚αž›αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαž“αŸ„αŸ‡αž‘αŸαŸ” αž˜αŸ’αž™αŸ‰αžΆαž„αžœαž·αž‰αž‘αŸ€αž XDP αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αž’αž“αž»αžœαžαŸ’αžαžαž€αŸ’αž€αžœαž·αž‡αŸ’αž‡αžΆαžŠαŸαžŸαŸ’αž˜αž»αž‚αžŸαŸ’αž˜αžΆαž‰ αžŠαŸ‚αž›αž›αžΎαžŸαž–αžΈαž“αŸαŸ‡αž‘αŸ…αž‘αŸ€αž αžœαžΆαž„αžΆαž™αžŸαŸ’αžšαž½αž›αž€αŸ’αž“αž»αž„αž€αžΆαžšαž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αžŠαŸ„αž™αž˜αž·αž“αž˜αžΆαž“αž€αžΆαžšαžšαŸ†αžαžΆαž“αž€αŸ’αž“αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž…αžšαžΆαž…αžšαžŽαŸαŸ” αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž˜αž·αž“αž”αž„αŸ’αž€αžΎαžαž”αž‰αŸ’αž αžΆαž’αŸ†αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž‘αŸ αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αž˜αž·αž“αž”αžŠαž·αžŸαŸαž’αž…αŸ†αž–αŸ„αŸ‡αž•αŸ’αž“αŸ‚αž€αž“αŸƒαž€αžΌαžŠαž€αž“αŸ’αž›αŸ‚αž„αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‘αŸαŸ”

αž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ’αž“αŸ‚αž€αž‘αžΈαž–αžΈαžš αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž”αŸ’αžšαž’αžΆαž“αž”αž‘αž‚αž½αžšαž±αŸ’αž™αž…αžΆαž”αŸ‹αž’αžΆαžšαž˜αŸ’αž˜αžŽαŸ αž™αžΎαž„αž“αžΉαž„αž”αŸ†αž–αŸαž‰αžαžΆαžšαžΆαž„αž’αžαž·αžαž·αž‡αž“αžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹ αž“αž·αž„αž€αžΆαžšαž•αŸ’αžαžΆαž…αŸ‹ αž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαžšαžΆαž”αŸ‹ αž“αž·αž„αžŸαžšαžŸαŸαžšαž§αž”αž€αžšαžŽαŸαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž€αž“αŸ’αž›αŸ‚αž„αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžŠαžΎαž˜αŸ’αž”αžΈαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžαž˜αŸ’αžšαž„αŸ”

αž―αž€αžŸαžΆαžšαž™αŸ„αž„:

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹