| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809 |
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright (c) 2019, Intel Corporation. */
- #include "ice_common.h"
- #include "ice_flow.h"
- #include <net/gre.h>
- /* Describe properties of a protocol header field */
- struct ice_flow_field_info {
- enum ice_flow_seg_hdr hdr;
- s16 off; /* Offset from start of a protocol header, in bits */
- u16 size; /* Size of fields in bits */
- u16 mask; /* 16-bit mask for field */
- };
- #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
- .hdr = _hdr, \
- .off = (_offset_bytes) * BITS_PER_BYTE, \
- .size = (_size_bytes) * BITS_PER_BYTE, \
- .mask = 0, \
- }
- #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
- .hdr = _hdr, \
- .off = (_offset_bytes) * BITS_PER_BYTE, \
- .size = (_size_bytes) * BITS_PER_BYTE, \
- .mask = _mask, \
- }
- /* Table containing properties of supported protocol header fields */
- static const
- struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
- /* Ether */
- /* ICE_FLOW_FIELD_IDX_ETH_DA */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
- /* ICE_FLOW_FIELD_IDX_ETH_SA */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
- /* ICE_FLOW_FIELD_IDX_S_VLAN */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)),
- /* ICE_FLOW_FIELD_IDX_C_VLAN */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)),
- /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)),
- /* IPv4 / IPv6 */
- /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
- ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc),
- /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
- ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0),
- /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
- ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00),
- /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
- ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff),
- /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
- ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff),
- /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
- ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00),
- /* ICE_FLOW_FIELD_IDX_IPV4_SA */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
- /* ICE_FLOW_FIELD_IDX_IPV4_DA */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
- /* ICE_FLOW_FIELD_IDX_IPV6_SA */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
- /* ICE_FLOW_FIELD_IDX_IPV6_DA */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),
- /* Transport */
- /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
- /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
- /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
- /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
- /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
- /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
- /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1),
- /* ARP */
- /* ICE_FLOW_FIELD_IDX_ARP_SIP */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)),
- /* ICE_FLOW_FIELD_IDX_ARP_DIP */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)),
- /* ICE_FLOW_FIELD_IDX_ARP_SHA */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
- /* ICE_FLOW_FIELD_IDX_ARP_DHA */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
- /* ICE_FLOW_FIELD_IDX_ARP_OP */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)),
- /* ICMP */
- /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1),
- /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1),
- /* GRE */
- /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
- sizeof_field(struct gre_full_hdr, key)),
- /* GTP */
- /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)),
- /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)),
- /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)),
- /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
- ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16),
- 0x3f00),
- /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)),
- /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)),
- /* PPPoE */
- /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)),
- /* PFCP */
- /* ICE_FLOW_FIELD_IDX_PFCP_SEID */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)),
- /* L2TPv3 */
- /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)),
- /* ESP */
- /* ICE_FLOW_FIELD_IDX_ESP_SPI */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)),
- /* AH */
- /* ICE_FLOW_FIELD_IDX_AH_SPI */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)),
- /* NAT_T_ESP */
- /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
- ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)),
- };
- /* Bitmaps indicating relevant packet types for a particular protocol header
- *
- * Packet types for packets with an Outer/First/Single MAC header
- */
- static const u32 ice_ptypes_mac_ofos[] = {
- 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
- 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
- 0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Innermost/Last MAC VLAN header */
- static const u32 ice_ptypes_macvlan_il[] = {
- 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
- 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
- * include IPv4 other PTYPEs
- */
- static const u32 ice_ptypes_ipv4_ofos[] = {
- 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
- 0x00000000, 0x00000155, 0x00000000, 0x00000000,
- 0x00000000, 0x000FC000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Outer/First/Single IPv4 header, includes
- * IPv4 other PTYPEs
- */
- static const u32 ice_ptypes_ipv4_ofos_all[] = {
- 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
- 0x00000000, 0x00000155, 0x00000000, 0x00000000,
- 0x00000000, 0x000FC000, 0x83E0F800, 0x00000101,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Innermost/Last IPv4 header */
- static const u32 ice_ptypes_ipv4_il[] = {
- 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
- 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x001FF800, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
- * include IPv6 other PTYPEs
- */
- static const u32 ice_ptypes_ipv6_ofos[] = {
- 0x00000000, 0x00000000, 0x77000000, 0x10002000,
- 0x00000000, 0x000002AA, 0x00000000, 0x00000000,
- 0x00000000, 0x03F00000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Outer/First/Single IPv6 header, includes
- * IPv6 other PTYPEs
- */
- static const u32 ice_ptypes_ipv6_ofos_all[] = {
- 0x00000000, 0x00000000, 0x77000000, 0x10002000,
- 0x00000000, 0x000002AA, 0x00000000, 0x00000000,
- 0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000206,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Innermost/Last IPv6 header */
- static const u32 ice_ptypes_ipv6_il[] = {
- 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
- 0x00000770, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
- static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
- 0x10C00000, 0x04000800, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Outermost/First ARP header */
- static const u32 ice_ptypes_arp_of[] = {
- 0x00000800, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
- static const u32 ice_ptypes_ipv4_il_no_l4[] = {
- 0x60000000, 0x18043008, 0x80000002, 0x6010c021,
- 0x00000008, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
- static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
- 0x00000000, 0x00000000, 0x43000000, 0x10002000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
- static const u32 ice_ptypes_ipv6_il_no_l4[] = {
- 0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
- 0x00000430, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* UDP Packet types for non-tunneled packets or tunneled
- * packets with inner UDP.
- */
- static const u32 ice_ptypes_udp_il[] = {
- 0x81000000, 0x20204040, 0x04000010, 0x80810102,
- 0x00000040, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00410000, 0x90842000, 0x00000007,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Innermost/Last TCP header */
- static const u32 ice_ptypes_tcp_il[] = {
- 0x04000000, 0x80810102, 0x10000040, 0x02040408,
- 0x00000102, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00820000, 0x21084000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Innermost/Last SCTP header */
- static const u32 ice_ptypes_sctp_il[] = {
- 0x08000000, 0x01020204, 0x20000081, 0x04080810,
- 0x00000204, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x01040000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Outermost/First ICMP header */
- static const u32 ice_ptypes_icmp_of[] = {
- 0x10000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Innermost/Last ICMP header */
- static const u32 ice_ptypes_icmp_il[] = {
- 0x00000000, 0x02040408, 0x40000102, 0x08101020,
- 0x00000408, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x42108000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Outermost/First GRE header */
- static const u32 ice_ptypes_gre_of[] = {
- 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
- 0x0000017E, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with an Innermost/Last MAC header */
- static const u32 ice_ptypes_mac_il[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for GTPC */
- static const u32 ice_ptypes_gtpc[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000180, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for GTPC with TEID */
- static const u32 ice_ptypes_gtpc_tid[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000060, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for GTPU */
- static const struct ice_ptype_attributes ice_attr_gtpu_session[] = {
- { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
- { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_SESSION },
- };
- static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
- { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
- { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
- };
- static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
- { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
- };
- static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
- { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
- { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
- };
- static const u32 ice_ptypes_gtpu[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for PPPoE */
- static const u32 ice_ptypes_pppoe[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with PFCP NODE header */
- static const u32 ice_ptypes_pfcp_node[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x80000000, 0x00000002,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with PFCP SESSION header */
- static const u32 ice_ptypes_pfcp_session[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000005,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for L2TPv3 */
- static const u32 ice_ptypes_l2tpv3[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000300,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for ESP */
- static const u32 ice_ptypes_esp[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000003, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for AH */
- static const u32 ice_ptypes_ah[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x0000000C, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Packet types for packets with NAT_T ESP header */
- static const u32 ice_ptypes_nat_t_esp[] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000030, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- static const u32 ice_ptypes_mac_non_ip_ofos[] = {
- 0x00000846, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- /* Manage parameters and info. used during the creation of a flow profile */
- struct ice_flow_prof_params {
- enum ice_block blk;
- u16 entry_length; /* # of bytes formatted entry will require */
- u8 es_cnt;
- struct ice_flow_prof *prof;
- /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
- * This will give us the direction flags.
- */
- struct ice_fv_word es[ICE_MAX_FV_WORDS];
- /* attributes can be used to add attributes to a particular PTYPE */
- const struct ice_ptype_attributes *attr;
- u16 attr_cnt;
- u16 mask[ICE_MAX_FV_WORDS];
- DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
- };
- #define ICE_FLOW_RSS_HDRS_INNER_MASK \
- (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
- ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
- ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
- ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
- ICE_FLOW_SEG_HDR_NAT_T_ESP)
- #define ICE_FLOW_SEG_HDRS_L3_MASK \
- (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
- #define ICE_FLOW_SEG_HDRS_L4_MASK \
- (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
- ICE_FLOW_SEG_HDR_SCTP)
- /* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
- #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER \
- (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
- /**
- * ice_flow_val_hdrs - validates packet segments for valid protocol headers
- * @segs: array of one or more packet segments that describe the flow
- * @segs_cnt: number of packet segments provided
- */
- static int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
- {
- u8 i;
- for (i = 0; i < segs_cnt; i++) {
- /* Multiple L3 headers */
- if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
- !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
- return -EINVAL;
- /* Multiple L4 headers */
- if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
- !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
- return -EINVAL;
- }
- return 0;
- }
- /* Sizes of fixed known protocol headers without header options */
- #define ICE_FLOW_PROT_HDR_SZ_MAC 14
- #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
- #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
- #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
- #define ICE_FLOW_PROT_HDR_SZ_ARP 28
- #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
- #define ICE_FLOW_PROT_HDR_SZ_TCP 20
- #define ICE_FLOW_PROT_HDR_SZ_UDP 8
- #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
- /**
- * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
- * @params: information about the flow to be processed
- * @seg: index of packet segment whose header size is to be determined
- */
- static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
- {
- u16 sz;
- /* L2 headers */
- sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
- ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
- /* L3 headers */
- if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
- sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
- else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
- sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
- else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
- sz += ICE_FLOW_PROT_HDR_SZ_ARP;
- else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
- /* An L3 header is required if L4 is specified */
- return 0;
- /* L4 headers */
- if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
- sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
- else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
- sz += ICE_FLOW_PROT_HDR_SZ_TCP;
- else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
- sz += ICE_FLOW_PROT_HDR_SZ_UDP;
- else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
- sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
- return sz;
- }
- /**
- * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
- * @params: information about the flow to be processed
- *
- * This function identifies the packet types associated with the protocol
- * headers being present in packet segments of the specified flow profile.
- */
- static int ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
- {
- struct ice_flow_prof *prof;
- u8 i;
- memset(params->ptypes, 0xff, sizeof(params->ptypes));
- prof = params->prof;
- for (i = 0; i < params->prof->segs_cnt; i++) {
- const unsigned long *src;
- u32 hdrs;
- hdrs = prof->segs[i].hdrs;
- if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
- src = !i ? (const unsigned long *)ice_ptypes_mac_ofos :
- (const unsigned long *)ice_ptypes_mac_il;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- }
- if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
- src = (const unsigned long *)ice_ptypes_macvlan_il;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- }
- if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
- bitmap_and(params->ptypes, params->ptypes,
- (const unsigned long *)ice_ptypes_arp_of,
- ICE_FLOW_PTYPE_MAX);
- }
- if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
- (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
- src = i ? (const unsigned long *)ice_ptypes_ipv4_il :
- (const unsigned long *)ice_ptypes_ipv4_ofos_all;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
- (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
- src = i ? (const unsigned long *)ice_ptypes_ipv6_il :
- (const unsigned long *)ice_ptypes_ipv6_ofos_all;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
- !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
- src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos_no_l4 :
- (const unsigned long *)ice_ptypes_ipv4_il_no_l4;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
- src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
- (const unsigned long *)ice_ptypes_ipv4_il;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
- !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
- src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos_no_l4 :
- (const unsigned long *)ice_ptypes_ipv6_il_no_l4;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
- src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
- (const unsigned long *)ice_ptypes_ipv6_il;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- }
- if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
- src = (const unsigned long *)ice_ptypes_mac_non_ip_ofos;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
- src = (const unsigned long *)ice_ptypes_pppoe;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else {
- src = (const unsigned long *)ice_ptypes_pppoe;
- bitmap_andnot(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- }
- if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
- src = (const unsigned long *)ice_ptypes_udp_il;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
- bitmap_and(params->ptypes, params->ptypes,
- (const unsigned long *)ice_ptypes_tcp_il,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
- src = (const unsigned long *)ice_ptypes_sctp_il;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- }
- if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
- src = !i ? (const unsigned long *)ice_ptypes_icmp_of :
- (const unsigned long *)ice_ptypes_icmp_il;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
- if (!i) {
- src = (const unsigned long *)ice_ptypes_gre_of;
- bitmap_and(params->ptypes, params->ptypes,
- src, ICE_FLOW_PTYPE_MAX);
- }
- } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
- src = (const unsigned long *)ice_ptypes_gtpc;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
- src = (const unsigned long *)ice_ptypes_gtpc_tid;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
- src = (const unsigned long *)ice_ptypes_gtpu;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- /* Attributes for GTP packet with downlink */
- params->attr = ice_attr_gtpu_down;
- params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
- } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
- src = (const unsigned long *)ice_ptypes_gtpu;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- /* Attributes for GTP packet with uplink */
- params->attr = ice_attr_gtpu_up;
- params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
- } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
- src = (const unsigned long *)ice_ptypes_gtpu;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- /* Attributes for GTP packet with Extension Header */
- params->attr = ice_attr_gtpu_eh;
- params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
- } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
- src = (const unsigned long *)ice_ptypes_gtpu;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
- src = (const unsigned long *)ice_ptypes_l2tpv3;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
- src = (const unsigned long *)ice_ptypes_esp;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
- src = (const unsigned long *)ice_ptypes_ah;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
- src = (const unsigned long *)ice_ptypes_nat_t_esp;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- }
- if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
- if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
- src = (const unsigned long *)ice_ptypes_pfcp_node;
- else
- src = (const unsigned long *)ice_ptypes_pfcp_session;
- bitmap_and(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- } else {
- src = (const unsigned long *)ice_ptypes_pfcp_node;
- bitmap_andnot(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- src = (const unsigned long *)ice_ptypes_pfcp_session;
- bitmap_andnot(params->ptypes, params->ptypes, src,
- ICE_FLOW_PTYPE_MAX);
- }
- }
- return 0;
- }
- /**
- * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
- * @hw: pointer to the HW struct
- * @params: information about the flow to be processed
- * @seg: packet segment index of the field to be extracted
- * @fld: ID of field to be extracted
- * @match: bit field of all fields
- *
- * This function determines the protocol ID, offset, and size of the given
- * field. It then allocates one or more extraction sequence entries for the
- * given field, and fill the entries with protocol ID and offset information.
- */
- static int
- ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
- u8 seg, enum ice_flow_field fld, u64 match)
- {
- enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
- enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
- u8 fv_words = hw->blk[params->blk].es.fvw;
- struct ice_flow_fld_info *flds;
- u16 cnt, ese_bits, i;
- u16 sib_mask = 0;
- u16 mask;
- u16 off;
- flds = params->prof->segs[seg].fields;
- switch (fld) {
- case ICE_FLOW_FIELD_IDX_ETH_DA:
- case ICE_FLOW_FIELD_IDX_ETH_SA:
- case ICE_FLOW_FIELD_IDX_S_VLAN:
- case ICE_FLOW_FIELD_IDX_C_VLAN:
- prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
- break;
- case ICE_FLOW_FIELD_IDX_ETH_TYPE:
- prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
- break;
- case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
- prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
- break;
- case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
- prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
- break;
- case ICE_FLOW_FIELD_IDX_IPV4_TTL:
- case ICE_FLOW_FIELD_IDX_IPV4_PROT:
- prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
- /* TTL and PROT share the same extraction seq. entry.
- * Each is considered a sibling to the other in terms of sharing
- * the same extraction sequence entry.
- */
- if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
- sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
- else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
- sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
- /* If the sibling field is also included, that field's
- * mask needs to be included.
- */
- if (match & BIT(sib))
- sib_mask = ice_flds_info[sib].mask;
- break;
- case ICE_FLOW_FIELD_IDX_IPV6_TTL:
- case ICE_FLOW_FIELD_IDX_IPV6_PROT:
- prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
- /* TTL and PROT share the same extraction seq. entry.
- * Each is considered a sibling to the other in terms of sharing
- * the same extraction sequence entry.
- */
- if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
- sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
- else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
- sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
- /* If the sibling field is also included, that field's
- * mask needs to be included.
- */
- if (match & BIT(sib))
- sib_mask = ice_flds_info[sib].mask;
- break;
- case ICE_FLOW_FIELD_IDX_IPV4_SA:
- case ICE_FLOW_FIELD_IDX_IPV4_DA:
- prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
- break;
- case ICE_FLOW_FIELD_IDX_IPV6_SA:
- case ICE_FLOW_FIELD_IDX_IPV6_DA:
- prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
- break;
- case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
- case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
- case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
- prot_id = ICE_PROT_TCP_IL;
- break;
- case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
- case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
- prot_id = ICE_PROT_UDP_IL_OR_S;
- break;
- case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
- case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
- prot_id = ICE_PROT_SCTP_IL;
- break;
- case ICE_FLOW_FIELD_IDX_GTPC_TEID:
- case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
- case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
- case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
- case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
- case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
- /* GTP is accessed through UDP OF protocol */
- prot_id = ICE_PROT_UDP_OF;
- break;
- case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
- prot_id = ICE_PROT_PPPOE;
- break;
- case ICE_FLOW_FIELD_IDX_PFCP_SEID:
- prot_id = ICE_PROT_UDP_IL_OR_S;
- break;
- case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
- prot_id = ICE_PROT_L2TPV3;
- break;
- case ICE_FLOW_FIELD_IDX_ESP_SPI:
- prot_id = ICE_PROT_ESP_F;
- break;
- case ICE_FLOW_FIELD_IDX_AH_SPI:
- prot_id = ICE_PROT_ESP_2;
- break;
- case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
- prot_id = ICE_PROT_UDP_IL_OR_S;
- break;
- case ICE_FLOW_FIELD_IDX_ARP_SIP:
- case ICE_FLOW_FIELD_IDX_ARP_DIP:
- case ICE_FLOW_FIELD_IDX_ARP_SHA:
- case ICE_FLOW_FIELD_IDX_ARP_DHA:
- case ICE_FLOW_FIELD_IDX_ARP_OP:
- prot_id = ICE_PROT_ARP_OF;
- break;
- case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
- case ICE_FLOW_FIELD_IDX_ICMP_CODE:
- /* ICMP type and code share the same extraction seq. entry */
- prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
- ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
- sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
- ICE_FLOW_FIELD_IDX_ICMP_CODE :
- ICE_FLOW_FIELD_IDX_ICMP_TYPE;
- break;
- case ICE_FLOW_FIELD_IDX_GRE_KEYID:
- prot_id = ICE_PROT_GRE_OF;
- break;
- default:
- return -EOPNOTSUPP;
- }
- /* Each extraction sequence entry is a word in size, and extracts a
- * word-aligned offset from a protocol header.
- */
- ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
- flds[fld].xtrct.prot_id = prot_id;
- flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
- ICE_FLOW_FV_EXTRACT_SZ;
- flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
- flds[fld].xtrct.idx = params->es_cnt;
- flds[fld].xtrct.mask = ice_flds_info[fld].mask;
- /* Adjust the next field-entry index after accommodating the number of
- * entries this field consumes
- */
- cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
- ese_bits);
- /* Fill in the extraction sequence entries needed for this field */
- off = flds[fld].xtrct.off;
- mask = flds[fld].xtrct.mask;
- for (i = 0; i < cnt; i++) {
- /* Only consume an extraction sequence entry if there is no
- * sibling field associated with this field or the sibling entry
- * already extracts the word shared with this field.
- */
- if (sib == ICE_FLOW_FIELD_IDX_MAX ||
- flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
- flds[sib].xtrct.off != off) {
- u8 idx;
- /* Make sure the number of extraction sequence required
- * does not exceed the block's capability
- */
- if (params->es_cnt >= fv_words)
- return -ENOSPC;
- /* some blocks require a reversed field vector layout */
- if (hw->blk[params->blk].es.reverse)
- idx = fv_words - params->es_cnt - 1;
- else
- idx = params->es_cnt;
- params->es[idx].prot_id = prot_id;
- params->es[idx].off = off;
- params->mask[idx] = mask | sib_mask;
- params->es_cnt++;
- }
- off += ICE_FLOW_FV_EXTRACT_SZ;
- }
- return 0;
- }
- /**
- * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
- * @hw: pointer to the HW struct
- * @params: information about the flow to be processed
- * @seg: index of packet segment whose raw fields are to be extracted
- */
- static int
- ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
- u8 seg)
- {
- u16 fv_words;
- u16 hdrs_sz;
- u8 i;
- if (!params->prof->segs[seg].raws_cnt)
- return 0;
- if (params->prof->segs[seg].raws_cnt >
- ARRAY_SIZE(params->prof->segs[seg].raws))
- return -ENOSPC;
- /* Offsets within the segment headers are not supported */
- hdrs_sz = ice_flow_calc_seg_sz(params, seg);
- if (!hdrs_sz)
- return -EINVAL;
- fv_words = hw->blk[params->blk].es.fvw;
- for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
- struct ice_flow_seg_fld_raw *raw;
- u16 off, cnt, j;
- raw = ¶ms->prof->segs[seg].raws[i];
- /* Storing extraction information */
- raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
- raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
- ICE_FLOW_FV_EXTRACT_SZ;
- raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
- BITS_PER_BYTE;
- raw->info.xtrct.idx = params->es_cnt;
- /* Determine the number of field vector entries this raw field
- * consumes.
- */
- cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
- (raw->info.src.last * BITS_PER_BYTE),
- (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
- off = raw->info.xtrct.off;
- for (j = 0; j < cnt; j++) {
- u16 idx;
- /* Make sure the number of extraction sequence required
- * does not exceed the block's capability
- */
- if (params->es_cnt >= hw->blk[params->blk].es.count ||
- params->es_cnt >= ICE_MAX_FV_WORDS)
- return -ENOSPC;
- /* some blocks require a reversed field vector layout */
- if (hw->blk[params->blk].es.reverse)
- idx = fv_words - params->es_cnt - 1;
- else
- idx = params->es_cnt;
- params->es[idx].prot_id = raw->info.xtrct.prot_id;
- params->es[idx].off = off;
- params->es_cnt++;
- off += ICE_FLOW_FV_EXTRACT_SZ;
- }
- }
- return 0;
- }
- /**
- * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
- * @hw: pointer to the HW struct
- * @params: information about the flow to be processed
- *
- * This function iterates through all matched fields in the given segments, and
- * creates an extraction sequence for the fields.
- */
- static int
- ice_flow_create_xtrct_seq(struct ice_hw *hw,
- struct ice_flow_prof_params *params)
- {
- struct ice_flow_prof *prof = params->prof;
- int status = 0;
- u8 i;
- for (i = 0; i < prof->segs_cnt; i++) {
- u64 match = params->prof->segs[i].match;
- enum ice_flow_field j;
- for_each_set_bit(j, (unsigned long *)&match,
- ICE_FLOW_FIELD_IDX_MAX) {
- status = ice_flow_xtract_fld(hw, params, i, j, match);
- if (status)
- return status;
- clear_bit(j, (unsigned long *)&match);
- }
- /* Process raw matching bytes */
- status = ice_flow_xtract_raws(hw, params, i);
- if (status)
- return status;
- }
- return status;
- }
- /**
- * ice_flow_proc_segs - process all packet segments associated with a profile
- * @hw: pointer to the HW struct
- * @params: information about the flow to be processed
- */
- static int
- ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
- {
- int status;
- status = ice_flow_proc_seg_hdrs(params);
- if (status)
- return status;
- status = ice_flow_create_xtrct_seq(hw, params);
- if (status)
- return status;
- switch (params->blk) {
- case ICE_BLK_FD:
- case ICE_BLK_RSS:
- status = 0;
- break;
- default:
- return -EOPNOTSUPP;
- }
- return status;
- }
- #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
- #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
- #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
- #define ICE_FLOW_FIND_PROF_CHK_SYMM 0x00000008
- /**
- * ice_flow_find_prof_conds - Find a profile matching headers and conditions
- * @hw: pointer to the HW struct
- * @blk: classification stage
- * @dir: flow direction
- * @segs: array of one or more packet segments that describe the flow
- * @segs_cnt: number of packet segments provided
- * @symm: symmetric setting for RSS profiles
- * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
- * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
- */
- static struct ice_flow_prof *
- ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
- enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
- u8 segs_cnt, bool symm, u16 vsi_handle, u32 conds)
- {
- struct ice_flow_prof *p, *prof = NULL;
- mutex_lock(&hw->fl_profs_locks[blk]);
- list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
- if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
- segs_cnt && segs_cnt == p->segs_cnt) {
- u8 i;
- /* Check for profile-VSI association if specified */
- if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
- ice_is_vsi_valid(hw, vsi_handle) &&
- !test_bit(vsi_handle, p->vsis))
- continue;
- /* Check for symmetric settings */
- if ((conds & ICE_FLOW_FIND_PROF_CHK_SYMM) &&
- p->symm != symm)
- continue;
- /* Protocol headers must be checked. Matched fields are
- * checked if specified.
- */
- for (i = 0; i < segs_cnt; i++)
- if (segs[i].hdrs != p->segs[i].hdrs ||
- ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
- segs[i].match != p->segs[i].match))
- break;
- /* A match is found if all segments are matched */
- if (i == segs_cnt) {
- prof = p;
- break;
- }
- }
- mutex_unlock(&hw->fl_profs_locks[blk]);
- return prof;
- }
- /**
- * ice_flow_find_prof_id - Look up a profile with given profile ID
- * @hw: pointer to the HW struct
- * @blk: classification stage
- * @prof_id: unique ID to identify this flow profile
- */
- static struct ice_flow_prof *
- ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
- {
- struct ice_flow_prof *p;
- list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
- if (p->id == prof_id)
- return p;
- return NULL;
- }
- /**
- * ice_flow_rem_entry_sync - Remove a flow entry
- * @hw: pointer to the HW struct
- * @blk: classification stage
- * @entry: flow entry to be removed
- */
- static int
- ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
- struct ice_flow_entry *entry)
- {
- if (!entry)
- return -EINVAL;
- list_del(&entry->l_entry);
- devm_kfree(ice_hw_to_dev(hw), entry);
- return 0;
- }
- /**
- * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
- * @hw: pointer to the HW struct
- * @blk: classification stage
- * @dir: flow direction
- * @segs: array of one or more packet segments that describe the flow
- * @segs_cnt: number of packet segments provided
- * @symm: symmetric setting for RSS profiles
- * @prof: stores the returned flow profile added
- *
- * Assumption: the caller has acquired the lock to the profile list
- */
- static int
- ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
- enum ice_flow_dir dir,
- struct ice_flow_seg_info *segs, u8 segs_cnt,
- bool symm, struct ice_flow_prof **prof)
- {
- struct ice_flow_prof_params *params;
- struct ice_prof_id *ids;
- int status;
- u64 prof_id;
- u8 i;
- if (!prof)
- return -EINVAL;
- ids = &hw->blk[blk].prof_id;
- prof_id = find_first_zero_bit(ids->id, ids->count);
- if (prof_id >= ids->count)
- return -ENOSPC;
- params = kzalloc(sizeof(*params), GFP_KERNEL);
- if (!params)
- return -ENOMEM;
- params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof),
- GFP_KERNEL);
- if (!params->prof) {
- status = -ENOMEM;
- goto free_params;
- }
- /* initialize extraction sequence to all invalid (0xff) */
- for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
- params->es[i].prot_id = ICE_PROT_INVALID;
- params->es[i].off = ICE_FV_OFFSET_INVAL;
- }
- params->blk = blk;
- params->prof->id = prof_id;
- params->prof->dir = dir;
- params->prof->segs_cnt = segs_cnt;
- params->prof->symm = symm;
- /* Make a copy of the segments that need to be persistent in the flow
- * profile instance
- */
- for (i = 0; i < segs_cnt; i++)
- memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs));
- status = ice_flow_proc_segs(hw, params);
- if (status) {
- ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
- goto out;
- }
- /* Add a HW profile for this flow profile */
- status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
- params->attr, params->attr_cnt, params->es,
- params->mask, symm, true);
- if (status) {
- ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
- goto out;
- }
- INIT_LIST_HEAD(¶ms->prof->entries);
- mutex_init(¶ms->prof->entries_lock);
- set_bit(prof_id, ids->id);
- *prof = params->prof;
- out:
- if (status)
- devm_kfree(ice_hw_to_dev(hw), params->prof);
- free_params:
- kfree(params);
- return status;
- }
- /**
- * ice_flow_rem_prof_sync - remove a flow profile
- * @hw: pointer to the hardware structure
- * @blk: classification stage
- * @prof: pointer to flow profile to remove
- *
- * Assumption: the caller has acquired the lock to the profile list
- */
- static int
- ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
- struct ice_flow_prof *prof)
- {
- int status;
- /* Remove all remaining flow entries before removing the flow profile */
- if (!list_empty(&prof->entries)) {
- struct ice_flow_entry *e, *t;
- mutex_lock(&prof->entries_lock);
- list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
- status = ice_flow_rem_entry_sync(hw, blk, e);
- if (status)
- break;
- }
- mutex_unlock(&prof->entries_lock);
- }
- /* Remove all hardware profiles associated with this flow profile */
- status = ice_rem_prof(hw, blk, prof->id);
- if (!status) {
- clear_bit(prof->id, hw->blk[blk].prof_id.id);
- list_del(&prof->l_entry);
- mutex_destroy(&prof->entries_lock);
- devm_kfree(ice_hw_to_dev(hw), prof);
- }
- return status;
- }
- /**
- * ice_flow_assoc_prof - associate a VSI with a flow profile
- * @hw: pointer to the hardware structure
- * @blk: classification stage
- * @prof: pointer to flow profile
- * @vsi_handle: software VSI handle
- *
- * Assumption: the caller has acquired the lock to the profile list
- * and the software VSI handle has been validated
- */
- static int
- ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
- struct ice_flow_prof *prof, u16 vsi_handle)
- {
- int status = 0;
- if (!test_bit(vsi_handle, prof->vsis)) {
- status = ice_add_prof_id_flow(hw, blk,
- ice_get_hw_vsi_num(hw,
- vsi_handle),
- prof->id);
- if (!status)
- set_bit(vsi_handle, prof->vsis);
- else
- ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
- status);
- }
- return status;
- }
- /**
- * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
- * @hw: pointer to the hardware structure
- * @blk: classification stage
- * @prof: pointer to flow profile
- * @vsi_handle: software VSI handle
- *
- * Assumption: the caller has acquired the lock to the profile list
- * and the software VSI handle has been validated
- */
- static int
- ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
- struct ice_flow_prof *prof, u16 vsi_handle)
- {
- int status = 0;
- if (test_bit(vsi_handle, prof->vsis)) {
- status = ice_rem_prof_id_flow(hw, blk,
- ice_get_hw_vsi_num(hw,
- vsi_handle),
- prof->id);
- if (!status)
- clear_bit(vsi_handle, prof->vsis);
- else
- ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
- status);
- }
- return status;
- }
- #define FLAG_GTP_EH_PDU_LINK BIT_ULL(13)
- #define FLAG_GTP_EH_PDU BIT_ULL(14)
- #define HI_BYTE_IN_WORD GENMASK(15, 8)
- #define LO_BYTE_IN_WORD GENMASK(7, 0)
- #define FLAG_GTPU_MSK \
- (FLAG_GTP_EH_PDU | FLAG_GTP_EH_PDU_LINK)
- #define FLAG_GTPU_UP \
- (FLAG_GTP_EH_PDU | FLAG_GTP_EH_PDU_LINK)
- #define FLAG_GTPU_DW FLAG_GTP_EH_PDU
- /**
- * ice_flow_set_parser_prof - Set flow profile based on the parsed profile info
- * @hw: pointer to the HW struct
- * @dest_vsi: dest VSI
- * @fdir_vsi: fdir programming VSI
- * @prof: stores parsed profile info from raw flow
- * @blk: classification blk
- *
- * Return: 0 on success or negative errno on failure.
- */
- int
- ice_flow_set_parser_prof(struct ice_hw *hw, u16 dest_vsi, u16 fdir_vsi,
- struct ice_parser_profile *prof, enum ice_block blk)
- {
- u64 id = find_first_bit(prof->ptypes, ICE_FLOW_PTYPE_MAX);
- struct ice_flow_prof_params *params __free(kfree);
- u8 fv_words = hw->blk[blk].es.fvw;
- int status;
- int i, idx;
- params = kzalloc(sizeof(*params), GFP_KERNEL);
- if (!params)
- return -ENOMEM;
- for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
- params->es[i].prot_id = ICE_PROT_INVALID;
- params->es[i].off = ICE_FV_OFFSET_INVAL;
- }
- for (i = 0; i < prof->fv_num; i++) {
- if (hw->blk[blk].es.reverse)
- idx = fv_words - i - 1;
- else
- idx = i;
- params->es[idx].prot_id = prof->fv[i].proto_id;
- params->es[idx].off = prof->fv[i].offset;
- params->mask[idx] = (((prof->fv[i].msk) << BITS_PER_BYTE) &
- HI_BYTE_IN_WORD) |
- (((prof->fv[i].msk) >> BITS_PER_BYTE) &
- LO_BYTE_IN_WORD);
- }
- switch (prof->flags) {
- case FLAG_GTPU_DW:
- params->attr = ice_attr_gtpu_down;
- params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
- break;
- case FLAG_GTPU_UP:
- params->attr = ice_attr_gtpu_up;
- params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
- break;
- default:
- if (prof->flags_msk & FLAG_GTPU_MSK) {
- params->attr = ice_attr_gtpu_session;
- params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_session);
- }
- break;
- }
- status = ice_add_prof(hw, blk, id, (u8 *)prof->ptypes,
- params->attr, params->attr_cnt,
- params->es, params->mask, false, false);
- if (status)
- return status;
- status = ice_flow_assoc_fdir_prof(hw, blk, dest_vsi, fdir_vsi, id);
- if (status)
- ice_rem_prof(hw, blk, id);
- return status;
- }
- /**
- * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
- * @hw: pointer to the HW struct
- * @blk: classification stage
- * @dir: flow direction
- * @segs: array of one or more packet segments that describe the flow
- * @segs_cnt: number of packet segments provided
- * @symm: symmetric setting for RSS profiles
- * @prof: stores the returned flow profile added
- */
- int
- ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
- struct ice_flow_seg_info *segs, u8 segs_cnt,
- bool symm, struct ice_flow_prof **prof)
- {
- int status;
- if (segs_cnt > ICE_FLOW_SEG_MAX)
- return -ENOSPC;
- if (!segs_cnt)
- return -EINVAL;
- if (!segs)
- return -EINVAL;
- status = ice_flow_val_hdrs(segs, segs_cnt);
- if (status)
- return status;
- mutex_lock(&hw->fl_profs_locks[blk]);
- status = ice_flow_add_prof_sync(hw, blk, dir, segs, segs_cnt,
- symm, prof);
- if (!status)
- list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
- mutex_unlock(&hw->fl_profs_locks[blk]);
- return status;
- }
- /**
- * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
- * @hw: pointer to the HW struct
- * @blk: the block for which the flow profile is to be removed
- * @prof_id: unique ID of the flow profile to be removed
- */
- int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
- {
- struct ice_flow_prof *prof;
- int status;
- mutex_lock(&hw->fl_profs_locks[blk]);
- prof = ice_flow_find_prof_id(hw, blk, prof_id);
- if (!prof) {
- status = -ENOENT;
- goto out;
- }
- /* prof becomes invalid after the call */
- status = ice_flow_rem_prof_sync(hw, blk, prof);
- out:
- mutex_unlock(&hw->fl_profs_locks[blk]);
- return status;
- }
- /**
- * ice_flow_add_entry - Add a flow entry
- * @hw: pointer to the HW struct
- * @blk: classification stage
- * @prof_id: ID of the profile to add a new flow entry to
- * @entry_id: unique ID to identify this flow entry
- * @vsi_handle: software VSI handle for the flow entry
- * @prio: priority of the flow entry
- * @data: pointer to a data buffer containing flow entry's match values/masks
- * @entry_h: pointer to buffer that receives the new flow entry's handle
- */
- int
- ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
- u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
- void *data, u64 *entry_h)
- {
- struct ice_flow_entry *e = NULL;
- struct ice_flow_prof *prof;
- int status;
- /* No flow entry data is expected for RSS */
- if (!entry_h || (!data && blk != ICE_BLK_RSS))
- return -EINVAL;
- if (!ice_is_vsi_valid(hw, vsi_handle))
- return -EINVAL;
- mutex_lock(&hw->fl_profs_locks[blk]);
- prof = ice_flow_find_prof_id(hw, blk, prof_id);
- if (!prof) {
- status = -ENOENT;
- } else {
- /* Allocate memory for the entry being added and associate
- * the VSI to the found flow profile
- */
- e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
- if (!e)
- status = -ENOMEM;
- else
- status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
- }
- mutex_unlock(&hw->fl_profs_locks[blk]);
- if (status)
- goto out;
- e->id = entry_id;
- e->vsi_handle = vsi_handle;
- e->prof = prof;
- e->priority = prio;
- switch (blk) {
- case ICE_BLK_FD:
- case ICE_BLK_RSS:
- break;
- default:
- status = -EOPNOTSUPP;
- goto out;
- }
- mutex_lock(&prof->entries_lock);
- list_add(&e->l_entry, &prof->entries);
- mutex_unlock(&prof->entries_lock);
- *entry_h = ICE_FLOW_ENTRY_HNDL(e);
- out:
- if (status)
- devm_kfree(ice_hw_to_dev(hw), e);
- return status;
- }
- /**
- * ice_flow_rem_entry - Remove a flow entry
- * @hw: pointer to the HW struct
- * @blk: classification stage
- * @entry_h: handle to the flow entry to be removed
- */
- int ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h)
- {
- struct ice_flow_entry *entry;
- struct ice_flow_prof *prof;
- int status = 0;
- if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
- return -EINVAL;
- entry = ICE_FLOW_ENTRY_PTR(entry_h);
- /* Retain the pointer to the flow profile as the entry will be freed */
- prof = entry->prof;
- if (prof) {
- mutex_lock(&prof->entries_lock);
- status = ice_flow_rem_entry_sync(hw, blk, entry);
- mutex_unlock(&prof->entries_lock);
- }
- return status;
- }
- /**
- * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
- * @seg: packet segment the field being set belongs to
- * @fld: field to be set
- * @field_type: type of the field
- * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
- * entry's input buffer
- * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
- * input buffer
- * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
- * entry's input buffer
- *
- * This helper function stores information of a field being matched, including
- * the type of the field and the locations of the value to match, the mask, and
- * the upper-bound value in the start of the input buffer for a flow entry.
- * This function should only be used for fixed-size data structures.
- *
- * This function also opportunistically determines the protocol headers to be
- * present based on the fields being set. Some fields cannot be used alone to
- * determine the protocol headers present. Sometimes, fields for particular
- * protocol headers are not matched. In those cases, the protocol headers
- * must be explicitly set.
- */
- static void
- ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
- enum ice_flow_fld_match_type field_type, u16 val_loc,
- u16 mask_loc, u16 last_loc)
- {
- u64 bit = BIT_ULL(fld);
- seg->match |= bit;
- if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
- seg->range |= bit;
- seg->fields[fld].type = field_type;
- seg->fields[fld].src.val = val_loc;
- seg->fields[fld].src.mask = mask_loc;
- seg->fields[fld].src.last = last_loc;
- ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
- }
- /**
- * ice_flow_set_fld - specifies locations of field from entry's input buffer
- * @seg: packet segment the field being set belongs to
- * @fld: field to be set
- * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
- * entry's input buffer
- * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
- * input buffer
- * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
- * entry's input buffer
- * @range: indicate if field being matched is to be in a range
- *
- * This function specifies the locations, in the form of byte offsets from the
- * start of the input buffer for a flow entry, from where the value to match,
- * the mask value, and upper value can be extracted. These locations are then
- * stored in the flow profile. When adding a flow entry associated with the
- * flow profile, these locations will be used to quickly extract the values and
- * create the content of a match entry. This function should only be used for
- * fixed-size data structures.
- */
- void
- ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
- u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
- {
- enum ice_flow_fld_match_type t = range ?
- ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
- ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
- }
- /**
- * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
- * @seg: packet segment the field being set belongs to
- * @off: offset of the raw field from the beginning of the segment in bytes
- * @len: length of the raw pattern to be matched
- * @val_loc: location of the value to match from entry's input buffer
- * @mask_loc: location of mask value from entry's input buffer
- *
- * This function specifies the offset of the raw field to be match from the
- * beginning of the specified packet segment, and the locations, in the form of
- * byte offsets from the start of the input buffer for a flow entry, from where
- * the value to match and the mask value to be extracted. These locations are
- * then stored in the flow profile. When adding flow entries to the associated
- * flow profile, these locations can be used to quickly extract the values to
- * create the content of a match entry. This function should only be used for
- * fixed-size data structures.
- */
- void
- ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
- u16 val_loc, u16 mask_loc)
- {
- if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
- seg->raws[seg->raws_cnt].off = off;
- seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
- seg->raws[seg->raws_cnt].info.src.val = val_loc;
- seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
- /* The "last" field is used to store the length of the field */
- seg->raws[seg->raws_cnt].info.src.last = len;
- }
- /* Overflows of "raws" will be handled as an error condition later in
- * the flow when this information is processed.
- */
- seg->raws_cnt++;
- }
- /**
- * ice_flow_rem_vsi_prof - remove VSI from flow profile
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @prof_id: unique ID to identify this flow profile
- *
- * This function removes the flow entries associated to the input
- * VSI handle and disassociate the VSI from the flow profile.
- */
- int ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id)
- {
- struct ice_flow_prof *prof;
- int status = 0;
- if (!ice_is_vsi_valid(hw, vsi_handle))
- return -EINVAL;
- /* find flow profile pointer with input package block and profile ID */
- prof = ice_flow_find_prof_id(hw, ICE_BLK_FD, prof_id);
- if (!prof) {
- ice_debug(hw, ICE_DBG_PKG, "Cannot find flow profile id=%llu\n",
- prof_id);
- return -ENOENT;
- }
- /* Remove all remaining flow entries before removing the flow profile */
- if (!list_empty(&prof->entries)) {
- struct ice_flow_entry *e, *t;
- mutex_lock(&prof->entries_lock);
- list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
- if (e->vsi_handle != vsi_handle)
- continue;
- status = ice_flow_rem_entry_sync(hw, ICE_BLK_FD, e);
- if (status)
- break;
- }
- mutex_unlock(&prof->entries_lock);
- }
- if (status)
- return status;
- /* disassociate the flow profile from sw VSI handle */
- status = ice_flow_disassoc_prof(hw, ICE_BLK_FD, prof, vsi_handle);
- if (status)
- ice_debug(hw, ICE_DBG_PKG, "ice_flow_disassoc_prof() failed with status=%d\n",
- status);
- return status;
- }
- #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
- (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
- #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
- (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
- #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
- (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
- #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
- (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
- ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
- ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
- /**
- * ice_flow_set_rss_seg_info - setup packet segments for RSS
- * @segs: pointer to the flow field segment(s)
- * @seg_cnt: segment count
- * @cfg: configure parameters
- *
- * Helper function to extract fields from hash bitmap and use flow
- * header value to set flow field segment for further use in flow
- * profile entry or removal.
- */
- static int
- ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
- const struct ice_rss_hash_cfg *cfg)
- {
- struct ice_flow_seg_info *seg;
- u64 val;
- u16 i;
- /* set inner most segment */
- seg = &segs[seg_cnt - 1];
- for_each_set_bit(i, (const unsigned long *)&cfg->hash_flds,
- (u16)ICE_FLOW_FIELD_IDX_MAX)
- ice_flow_set_fld(seg, (enum ice_flow_field)i,
- ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
- ICE_FLOW_FLD_OFF_INVAL, false);
- ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
- /* set outer most header */
- if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
- segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
- ICE_FLOW_SEG_HDR_IPV_OTHER;
- else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
- segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
- ICE_FLOW_SEG_HDR_IPV_OTHER;
- if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
- ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
- return -EINVAL;
- val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
- if (val && !is_power_of_2(val))
- return -EIO;
- val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
- if (val && !is_power_of_2(val))
- return -EIO;
- return 0;
- }
- /**
- * ice_rem_vsi_rss_list - remove VSI from RSS list
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- *
- * Remove the VSI from all RSS configurations in the list.
- */
- void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
- {
- struct ice_rss_cfg *r, *tmp;
- if (list_empty(&hw->rss_list_head))
- return;
- mutex_lock(&hw->rss_locks);
- list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
- if (test_and_clear_bit(vsi_handle, r->vsis))
- if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
- list_del(&r->l_entry);
- devm_kfree(ice_hw_to_dev(hw), r);
- }
- mutex_unlock(&hw->rss_locks);
- }
- /**
- * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- *
- * This function will iterate through all flow profiles and disassociate
- * the VSI from that profile. If the flow profile has no VSIs it will
- * be removed.
- */
- int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
- {
- const enum ice_block blk = ICE_BLK_RSS;
- struct ice_flow_prof *p, *t;
- int status = 0;
- if (!ice_is_vsi_valid(hw, vsi_handle))
- return -EINVAL;
- if (list_empty(&hw->fl_profs[blk]))
- return 0;
- mutex_lock(&hw->rss_locks);
- list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
- if (test_bit(vsi_handle, p->vsis)) {
- status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
- if (status)
- break;
- if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
- status = ice_flow_rem_prof(hw, blk, p->id);
- if (status)
- break;
- }
- }
- mutex_unlock(&hw->rss_locks);
- return status;
- }
- /**
- * ice_get_rss_hdr_type - get a RSS profile's header type
- * @prof: RSS flow profile
- */
- static enum ice_rss_cfg_hdr_type
- ice_get_rss_hdr_type(struct ice_flow_prof *prof)
- {
- if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
- return ICE_RSS_OUTER_HEADERS;
- } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
- const struct ice_flow_seg_info *s;
- s = &prof->segs[ICE_RSS_OUTER_HEADERS];
- if (s->hdrs == ICE_FLOW_SEG_HDR_NONE)
- return ICE_RSS_INNER_HEADERS;
- if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4)
- return ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
- if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6)
- return ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
- }
- return ICE_RSS_ANY_HEADERS;
- }
- static bool
- ice_rss_match_prof(struct ice_rss_cfg *r, struct ice_flow_prof *prof,
- enum ice_rss_cfg_hdr_type hdr_type)
- {
- return (r->hash.hdr_type == hdr_type &&
- r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
- r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs);
- }
- /**
- * ice_rem_rss_list - remove RSS configuration from list
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @prof: pointer to flow profile
- *
- * Assumption: lock has already been acquired for RSS list
- */
- static void
- ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
- {
- enum ice_rss_cfg_hdr_type hdr_type;
- struct ice_rss_cfg *r, *tmp;
- /* Search for RSS hash fields associated to the VSI that match the
- * hash configurations associated to the flow profile. If found
- * remove from the RSS entry list of the VSI context and delete entry.
- */
- hdr_type = ice_get_rss_hdr_type(prof);
- list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
- if (ice_rss_match_prof(r, prof, hdr_type)) {
- clear_bit(vsi_handle, r->vsis);
- if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
- list_del(&r->l_entry);
- devm_kfree(ice_hw_to_dev(hw), r);
- }
- return;
- }
- }
- /**
- * ice_add_rss_list - add RSS configuration to list
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @prof: pointer to flow profile
- *
- * Assumption: lock has already been acquired for RSS list
- */
- static int
- ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
- {
- enum ice_rss_cfg_hdr_type hdr_type;
- struct ice_rss_cfg *r, *rss_cfg;
- hdr_type = ice_get_rss_hdr_type(prof);
- list_for_each_entry(r, &hw->rss_list_head, l_entry)
- if (ice_rss_match_prof(r, prof, hdr_type)) {
- set_bit(vsi_handle, r->vsis);
- return 0;
- }
- rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
- GFP_KERNEL);
- if (!rss_cfg)
- return -ENOMEM;
- rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match;
- rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
- rss_cfg->hash.hdr_type = hdr_type;
- rss_cfg->hash.symm = prof->symm;
- set_bit(vsi_handle, rss_cfg->vsis);
- list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
- return 0;
- }
- /**
- * ice_rss_config_xor_word - set the HSYMM registers for one input set word
- * @hw: pointer to the hardware structure
- * @prof_id: RSS hardware profile id
- * @src: the FV index used by the protocol's source field
- * @dst: the FV index used by the protocol's destination field
- *
- * Write to the HSYMM register with the index of @src FV the value of the @dst
- * FV index. This will tell the hardware to XOR HSYMM[src] with INSET[dst]
- * while calculating the RSS input set.
- */
- static void
- ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
- {
- u32 val, reg, bits_shift;
- u8 reg_idx;
- reg_idx = src / GLQF_HSYMM_REG_SIZE;
- bits_shift = ((src % GLQF_HSYMM_REG_SIZE) << 3);
- val = dst | GLQF_HSYMM_ENABLE_BIT;
- reg = rd32(hw, GLQF_HSYMM(prof_id, reg_idx));
- reg = (reg & ~(0xff << bits_shift)) | (val << bits_shift);
- wr32(hw, GLQF_HSYMM(prof_id, reg_idx), reg);
- }
- /**
- * ice_rss_config_xor - set the symmetric registers for a profile's protocol
- * @hw: pointer to the hardware structure
- * @prof_id: RSS hardware profile id
- * @src: the FV index used by the protocol's source field
- * @dst: the FV index used by the protocol's destination field
- * @len: length of the source/destination fields in words
- */
- static void
- ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
- {
- int fv_last_word =
- ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
- int i;
- for (i = 0; i < len; i++) {
- ice_rss_config_xor_word(hw, prof_id,
- /* Yes, field vector in GLQF_HSYMM and
- * GLQF_HINSET is inversed!
- */
- fv_last_word - (src + i),
- fv_last_word - (dst + i));
- ice_rss_config_xor_word(hw, prof_id,
- fv_last_word - (dst + i),
- fv_last_word - (src + i));
- }
- }
- /**
- * ice_rss_set_symm - set the symmetric settings for an RSS profile
- * @hw: pointer to the hardware structure
- * @prof: pointer to flow profile
- *
- * The symmetric hash will result from XORing the protocol's fields with
- * indexes in GLQF_HSYMM and GLQF_HINSET. This function configures the profile's
- * GLQF_HSYMM registers.
- */
- static void ice_rss_set_symm(struct ice_hw *hw, struct ice_flow_prof *prof)
- {
- struct ice_prof_map *map;
- u8 prof_id, m;
- mutex_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
- map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
- if (map)
- prof_id = map->prof_id;
- mutex_unlock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
- if (!map)
- return;
- /* clear to default */
- for (m = 0; m < GLQF_HSYMM_REG_PER_PROF; m++)
- wr32(hw, GLQF_HSYMM(prof_id, m), 0);
- if (prof->symm) {
- struct ice_flow_seg_xtrct *ipv4_src, *ipv4_dst;
- struct ice_flow_seg_xtrct *ipv6_src, *ipv6_dst;
- struct ice_flow_seg_xtrct *sctp_src, *sctp_dst;
- struct ice_flow_seg_xtrct *tcp_src, *tcp_dst;
- struct ice_flow_seg_xtrct *udp_src, *udp_dst;
- struct ice_flow_seg_info *seg;
- seg = &prof->segs[prof->segs_cnt - 1];
- ipv4_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
- ipv4_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
- ipv6_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
- ipv6_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
- tcp_src = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
- tcp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
- udp_src = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
- udp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
- sctp_src = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
- sctp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
- /* xor IPv4 */
- if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
- ice_rss_config_xor(hw, prof_id,
- ipv4_src->idx, ipv4_dst->idx, 2);
- /* xor IPv6 */
- if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
- ice_rss_config_xor(hw, prof_id,
- ipv6_src->idx, ipv6_dst->idx, 8);
- /* xor TCP */
- if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
- ice_rss_config_xor(hw, prof_id,
- tcp_src->idx, tcp_dst->idx, 1);
- /* xor UDP */
- if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
- ice_rss_config_xor(hw, prof_id,
- udp_src->idx, udp_dst->idx, 1);
- /* xor SCTP */
- if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
- ice_rss_config_xor(hw, prof_id,
- sctp_src->idx, sctp_dst->idx, 1);
- }
- }
- /**
- * ice_add_rss_cfg_sync - add an RSS configuration
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @cfg: configure parameters
- *
- * Assumption: lock has already been acquired for RSS list
- */
- static int
- ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
- const struct ice_rss_hash_cfg *cfg)
- {
- const enum ice_block blk = ICE_BLK_RSS;
- struct ice_flow_prof *prof = NULL;
- struct ice_flow_seg_info *segs;
- u8 segs_cnt;
- int status;
- segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
- ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
- segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
- if (!segs)
- return -ENOMEM;
- /* Construct the packet segment info from the hashed fields */
- status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
- if (status)
- goto exit;
- /* Search for a flow profile that has matching headers, hash fields,
- * symm and has the input VSI associated to it. If found, no further
- * operations required and exit.
- */
- prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
- cfg->symm, vsi_handle,
- ICE_FLOW_FIND_PROF_CHK_FLDS |
- ICE_FLOW_FIND_PROF_CHK_SYMM |
- ICE_FLOW_FIND_PROF_CHK_VSI);
- if (prof)
- goto exit;
- /* Check if a flow profile exists with the same protocol headers and
- * associated with the input VSI. If so disassociate the VSI from
- * this profile. The VSI will be added to a new profile created with
- * the protocol header and new hash field configuration.
- */
- prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
- cfg->symm, vsi_handle,
- ICE_FLOW_FIND_PROF_CHK_VSI);
- if (prof) {
- status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
- if (!status)
- ice_rem_rss_list(hw, vsi_handle, prof);
- else
- goto exit;
- /* Remove profile if it has no VSIs associated */
- if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
- status = ice_flow_rem_prof(hw, blk, prof->id);
- if (status)
- goto exit;
- }
- }
- /* Search for a profile that has the same match fields and symmetric
- * setting. If this exists then associate the VSI to this profile.
- */
- prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
- cfg->symm, vsi_handle,
- ICE_FLOW_FIND_PROF_CHK_SYMM |
- ICE_FLOW_FIND_PROF_CHK_FLDS);
- if (prof) {
- status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
- if (!status)
- status = ice_add_rss_list(hw, vsi_handle, prof);
- goto exit;
- }
- /* Create a new flow profile with packet segment information. */
- status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
- segs, segs_cnt, cfg->symm, &prof);
- if (status)
- goto exit;
- prof->symm = cfg->symm;
- ice_rss_set_symm(hw, prof);
- status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
- /* If association to a new flow profile failed then this profile can
- * be removed.
- */
- if (status) {
- ice_flow_rem_prof(hw, blk, prof->id);
- goto exit;
- }
- status = ice_add_rss_list(hw, vsi_handle, prof);
- exit:
- kfree(segs);
- return status;
- }
- /**
- * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
- * @hw: pointer to the hardware structure
- * @vsi: VSI to add the RSS configuration to
- * @cfg: configure parameters
- *
- * This function will generate a flow profile based on fields associated with
- * the input fields to hash on, the flow type and use the VSI number to add
- * a flow entry to the profile.
- */
- int
- ice_add_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi,
- const struct ice_rss_hash_cfg *cfg)
- {
- struct ice_rss_hash_cfg local_cfg;
- u16 vsi_handle;
- int status;
- if (!vsi)
- return -EINVAL;
- vsi_handle = vsi->idx;
- if (!ice_is_vsi_valid(hw, vsi_handle) ||
- !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
- cfg->hash_flds == ICE_HASH_INVALID)
- return -EINVAL;
- mutex_lock(&hw->rss_locks);
- local_cfg = *cfg;
- if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
- status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
- } else {
- local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
- status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
- if (!status) {
- local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
- status = ice_add_rss_cfg_sync(hw, vsi_handle,
- &local_cfg);
- }
- }
- mutex_unlock(&hw->rss_locks);
- return status;
- }
- /**
- * ice_rem_rss_cfg_sync - remove an existing RSS configuration
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @cfg: configure parameters
- *
- * Assumption: lock has already been acquired for RSS list
- */
- static int
- ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
- const struct ice_rss_hash_cfg *cfg)
- {
- const enum ice_block blk = ICE_BLK_RSS;
- struct ice_flow_seg_info *segs;
- struct ice_flow_prof *prof;
- u8 segs_cnt;
- int status;
- segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
- ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
- segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
- if (!segs)
- return -ENOMEM;
- /* Construct the packet segment info from the hashed fields */
- status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
- if (status)
- goto out;
- prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
- cfg->symm, vsi_handle,
- ICE_FLOW_FIND_PROF_CHK_FLDS);
- if (!prof) {
- status = -ENOENT;
- goto out;
- }
- status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
- if (status)
- goto out;
- /* Remove RSS configuration from VSI context before deleting
- * the flow profile.
- */
- ice_rem_rss_list(hw, vsi_handle, prof);
- if (bitmap_empty(prof->vsis, ICE_MAX_VSI))
- status = ice_flow_rem_prof(hw, blk, prof->id);
- out:
- kfree(segs);
- return status;
- }
- /**
- * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @cfg: configure parameters
- *
- * This function will lookup the flow profile based on the input
- * hash field bitmap, iterate through the profile entry list of
- * that profile and find entry associated with input VSI to be
- * removed. Calls are made to underlying flow apis which will in
- * turn build or update buffers for RSS XLT1 section.
- */
- int
- ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
- const struct ice_rss_hash_cfg *cfg)
- {
- struct ice_rss_hash_cfg local_cfg;
- int status;
- if (!ice_is_vsi_valid(hw, vsi_handle) ||
- !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
- cfg->hash_flds == ICE_HASH_INVALID)
- return -EINVAL;
- mutex_lock(&hw->rss_locks);
- local_cfg = *cfg;
- if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
- status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
- } else {
- local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
- status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
- if (!status) {
- local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
- status = ice_rem_rss_cfg_sync(hw, vsi_handle,
- &local_cfg);
- }
- }
- mutex_unlock(&hw->rss_locks);
- return status;
- }
- /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
- * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
- * convert its values to their appropriate flow L3, L4 values.
- */
- #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
- #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
- #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
- #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
- (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
- ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
- #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
- #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
- #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
- (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
- #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
- (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
- ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
- /**
- * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
- * @hw: pointer to the hardware structure
- * @vsi: VF's VSI
- * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
- *
- * This function will take the hash bitmap provided by the AVF driver via a
- * message, convert it to ICE-compatible values, and configure RSS flow
- * profiles.
- */
- int ice_add_avf_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi, u64 avf_hash)
- {
- struct ice_rss_hash_cfg hcfg;
- u16 vsi_handle;
- int status = 0;
- u64 hash_flds;
- if (!vsi)
- return -EINVAL;
- vsi_handle = vsi->idx;
- if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
- !ice_is_vsi_valid(hw, vsi_handle))
- return -EINVAL;
- /* Make sure no unsupported bits are specified */
- if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
- ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
- return -EIO;
- hash_flds = avf_hash;
- /* Always create an L3 RSS configuration for any L4 RSS configuration */
- if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
- hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
- if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
- hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
- /* Create the corresponding RSS configuration for each valid hash bit */
- while (hash_flds) {
- u64 rss_hash = ICE_HASH_INVALID;
- if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
- if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV4;
- hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
- } else if (hash_flds &
- ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV4 |
- ICE_FLOW_HASH_TCP_PORT;
- hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
- } else if (hash_flds &
- ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV4 |
- ICE_FLOW_HASH_UDP_PORT;
- hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
- } else if (hash_flds &
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
- rss_hash = ICE_FLOW_HASH_IPV4 |
- ICE_FLOW_HASH_SCTP_PORT;
- hash_flds &=
- ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
- }
- } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
- if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV6;
- hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
- } else if (hash_flds &
- ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV6 |
- ICE_FLOW_HASH_TCP_PORT;
- hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
- } else if (hash_flds &
- ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
- rss_hash = ICE_FLOW_HASH_IPV6 |
- ICE_FLOW_HASH_UDP_PORT;
- hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
- } else if (hash_flds &
- BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
- rss_hash = ICE_FLOW_HASH_IPV6 |
- ICE_FLOW_HASH_SCTP_PORT;
- hash_flds &=
- ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
- }
- }
- if (rss_hash == ICE_HASH_INVALID)
- return -EIO;
- hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
- hcfg.hash_flds = rss_hash;
- hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
- hcfg.symm = false;
- status = ice_add_rss_cfg(hw, vsi, &hcfg);
- if (status)
- break;
- }
- return status;
- }
- static bool rss_cfg_symm_valid(u64 hfld)
- {
- return !((!!(hfld & ICE_FLOW_HASH_FLD_IPV4_SA) ^
- !!(hfld & ICE_FLOW_HASH_FLD_IPV4_DA)) ||
- (!!(hfld & ICE_FLOW_HASH_FLD_IPV6_SA) ^
- !!(hfld & ICE_FLOW_HASH_FLD_IPV6_DA)) ||
- (!!(hfld & ICE_FLOW_HASH_FLD_TCP_SRC_PORT) ^
- !!(hfld & ICE_FLOW_HASH_FLD_TCP_DST_PORT)) ||
- (!!(hfld & ICE_FLOW_HASH_FLD_UDP_SRC_PORT) ^
- !!(hfld & ICE_FLOW_HASH_FLD_UDP_DST_PORT)) ||
- (!!(hfld & ICE_FLOW_HASH_FLD_SCTP_SRC_PORT) ^
- !!(hfld & ICE_FLOW_HASH_FLD_SCTP_DST_PORT)));
- }
- /**
- * ice_set_rss_cfg_symm - set symmtery for all VSI's RSS configurations
- * @hw: pointer to the hardware structure
- * @vsi: VSI to set/unset Symmetric RSS
- * @symm: TRUE to set Symmetric RSS hashing
- */
- int ice_set_rss_cfg_symm(struct ice_hw *hw, struct ice_vsi *vsi, bool symm)
- {
- struct ice_rss_hash_cfg local;
- struct ice_rss_cfg *r, *tmp;
- u16 vsi_handle = vsi->idx;
- int status = 0;
- if (!ice_is_vsi_valid(hw, vsi_handle))
- return -EINVAL;
- mutex_lock(&hw->rss_locks);
- list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) {
- if (test_bit(vsi_handle, r->vsis) && r->hash.symm != symm) {
- local = r->hash;
- local.symm = symm;
- if (symm && !rss_cfg_symm_valid(r->hash.hash_flds))
- continue;
- status = ice_add_rss_cfg_sync(hw, vsi_handle, &local);
- if (status)
- break;
- }
- }
- mutex_unlock(&hw->rss_locks);
- return status;
- }
- /**
- * ice_replay_rss_cfg - replay RSS configurations associated with VSI
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- */
- int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
- {
- struct ice_rss_cfg *r;
- int status = 0;
- if (!ice_is_vsi_valid(hw, vsi_handle))
- return -EINVAL;
- mutex_lock(&hw->rss_locks);
- list_for_each_entry(r, &hw->rss_list_head, l_entry) {
- if (test_bit(vsi_handle, r->vsis)) {
- status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
- if (status)
- break;
- }
- }
- mutex_unlock(&hw->rss_locks);
- return status;
- }
- /**
- * ice_get_rss_cfg - returns hashed fields for the given header types
- * @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @hdrs: protocol header type
- * @symm: whether the RSS is symmetric (bool, output)
- *
- * This function will return the match fields of the first instance of flow
- * profile having the given header types and containing input VSI
- */
- u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs, bool *symm)
- {
- u64 rss_hash = ICE_HASH_INVALID;
- struct ice_rss_cfg *r;
- /* verify if the protocol header is non zero and VSI is valid */
- if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
- return ICE_HASH_INVALID;
- mutex_lock(&hw->rss_locks);
- list_for_each_entry(r, &hw->rss_list_head, l_entry)
- if (test_bit(vsi_handle, r->vsis) &&
- r->hash.addl_hdrs == hdrs) {
- rss_hash = r->hash.hash_flds;
- *symm = r->hash.symm;
- break;
- }
- mutex_unlock(&hw->rss_locks);
- return rss_hash;
- }
|