የBPF እና eBPF አጭር መግቢያ

ሰላም ሀብር! የሚለቀቅ መጽሐፍ እያዘጋጀን መሆኑን ለማሳወቅ እንወዳለን።የሊኑክስ ታዛቢነት ከ BPF ጋር".

የBPF እና eBPF አጭር መግቢያ
የBPF ቨርቹዋል ማሽን በዝግመተ ለውጥ ስለቀጠለ እና በተግባር በንቃት ጥቅም ላይ የሚውል በመሆኑ ዋና አቅሞቹን እና አሁን ያለውን ሁኔታ የሚገልጽ ጽሑፍ ለእርስዎ ተርጉመናል።

ከቅርብ ዓመታት ወዲህ የፕሮግራም አወጣጥ መሳሪያዎች እና ቴክኒኮች ከፍተኛ አፈጻጸም ያለው የፓኬት ሂደት በሚያስፈልግበት ጊዜ የሊኑክስ ኮርነልን ውስንነት ለማካካስ ተወዳጅ እየሆኑ መጥተዋል። የዚህ ዓይነቱ በጣም ተወዳጅ ቴክኒኮች አንዱ ይባላል የከርነል ማለፊያ (ከርነል ማለፊያ) እና የከርነል ኔትወርክን ንብርብር በማለፍ ከተጠቃሚው ቦታ ሁሉንም የፓኬቶች ሂደት እንዲያከናውን ይፈቅዳል። ከርነልን ማለፍ የኔትወርክ ካርዱን መቆጣጠርንም ያካትታል የተጠቃሚ ቦታ. በሌላ አነጋገር ከኔትወርክ ካርድ ጋር ስንሰራ በሾፌሩ ላይ እንተማመናለን። የተጠቃሚ ቦታ.

የኔትዎርክ ካርዱን ሙሉ ቁጥጥር ወደ ተጠቃሚ-ቦታ ፕሮግራም በማሸጋገር የከርነል ራስጌን እንቀንሳለን (የአውድ መቀየር፣ የአውታረ መረብ ንብርብር ማቀናበር፣ ማቋረጦች፣ ወዘተ) በ10Gb/s ወይም ከዚያ በላይ በሆነ ፍጥነት ሲሮጥ በጣም አስፈላጊ ነው። የከርነል ማለፊያ እና የሌሎች ባህሪያት ጥምረት (ባች ማቀነባበሪያ) እና በጥንቃቄ የአፈፃፀም ማስተካከያ (NUMA የሂሳብ አያያዝ, የሲፒዩ ማግለልወዘተ) በተጠቃሚ ቦታ ከፍተኛ አፈጻጸም ካለው የአውታረ መረብ ሂደት መሰረታዊ ነገሮች ጋር ይዛመዳል። ምናልባት የዚህ አዲስ የፓኬት ሂደት ምሳሌ ምሳሌ ነው። ዲ.ዲ.ኬ. ከ ኢንቴል (የውሂብ አውሮፕላን ልማት ኪትየ Cisco's VPP (Vector Packet Processing)፣ Netmap እና በእርግጥ፣ ጨምሮ ሌሎች የታወቁ መሳሪያዎች እና ቴክኒኮች ቢኖሩም፣ Snabb.

በተጠቃሚ ቦታ ላይ የአውታረ መረብ መስተጋብርን ማደራጀት በርካታ ጉዳቶች አሉት።

  • የስርዓተ ክወናው ከርነል የሃርድዌር ሀብቶች ረቂቅ ንብርብር ነው። የተጠቃሚ ቦታ ፕሮግራሞች ሃብቶቻቸውን በቀጥታ ማስተዳደር ስላለባቸው የራሳቸውን ሃርድዌር ማስተዳደር አለባቸው። ይህ ማለት ብዙውን ጊዜ የራስዎን ሾፌሮች ፕሮግራም ማውጣት አለብዎት።
  • የከርነል ቦታን ሙሉ በሙሉ ስለምንተው፣ በከርነል የቀረበውን ሁሉንም የአውታረ መረብ ተግባራትም እንተዋለን። የተጠቃሚ ቦታ ፕሮግራሞች ቀድሞውኑ በከርነል ወይም በስርዓተ ክወናው ሊቀርቡ የሚችሉ ባህሪያትን እንደገና መተግበር አለባቸው።
  • ፕሮግራሞች በማጠሪያ ሁነታ ይሰራሉ, ይህም ግንኙነታቸውን በቁም ነገር የሚገድብ እና ከሌሎች የስርዓተ ክወና ክፍሎች ጋር እንዳይዋሃዱ ያግዳቸዋል.

በመሠረቱ፣ በተጠቃሚ ቦታ ውስጥ አውታረመረብ ሲገናኙ፣ የአፈጻጸም ትርፎች የሚገኘው የፓኬት ማቀነባበሪያን ከከርነል ወደ ተጠቃሚ ቦታ በማንቀሳቀስ ነው። XDP በትክክል የተገላቢጦሽ ነው፡ የኔትወርክ ፕሮግራሞችን ከተጠቃሚ ቦታ (ማጣሪያዎች፣ ፈታሾች፣ ራውቲንግ ወዘተ) ወደ ከርነል አካባቢ ያንቀሳቅሳል። XDP የኔትወርክ ተግባርን እንድንፈጽም ያስችለናል አንድ ፓኬት የአውታረ መረብ በይነገጽ ላይ እንደገባ እና ወደ የከርነል ኔትወርክ ንዑስ ስርዓት መንቀሳቀስ ከመጀመሩ በፊት። በዚህ ምክንያት የፓኬት ማቀነባበሪያ ፍጥነት በከፍተኛ ሁኔታ ይጨምራል. ነገር ግን፣ ኮርነሉ ተጠቃሚው ፕሮግራሞቻቸውን በከርነል ቦታ ላይ እንዲፈጽም የሚፈቅደው እንዴት ነው? ይህንን ጥያቄ ከመመለሳችን በፊት፣ BPF ምን እንደሆነ እንይ።

BPF እና eBPF

ግራ የሚያጋባ ስም ቢኖረውም, BPF (በርክሌይ ፓኬት ማጣሪያ) በእውነቱ, ምናባዊ ማሽን ሞዴል ነው. ይህ ቨርቹዋል ማሽን በመጀመሪያ የተሰራው የፓኬት ማጣሪያን ለማስተናገድ ነው፡ ስለዚህም ስሙ።

BPF በመጠቀም በጣም ታዋቂ ከሆኑ መሳሪያዎች አንዱ ነው tcpdump. በመጠቀም ፓኬቶችን ሲይዙ tcpdump ተጠቃሚው እሽጎችን ለማጣራት አገላለጽ መግለጽ ይችላል። ከዚህ አገላለጽ ጋር የሚዛመዱ እሽጎች ብቻ ይያዛሉ። ለምሳሌ "" የሚለው አገላለጽ.tcp dst port 80” ወደብ 80 የሚደርሱትን ሁሉንም የTCP ፓኬጆች ይመለከታል። አቀናባሪው ይህንን አገላለጽ ወደ BPF ባይት ኮድ በመቀየር ሊያሳጥረው ይችላል።

$ sudo tcpdump -d "tcp dst port 80"
(000) ldh [12] (001) jeq #0x86dd jt 2 jf 6
(002) ldb [20] (003) jeq #0x6 jt 4 jf 15
(004) ldh [56] (005) jeq #0x50 jt 14 jf 15
(006) jeq #0x800 jt 7 jf 15
(007) ldb [23] (008) jeq #0x6 jt 9 jf 15
(009) ldh [20] (010) jset #0x1fff jt 15 jf 11
(011) ldxb 4*([14]&0xf)
(012) ldh [x + 16] (013) jeq #0x50 jt 14 jf 15
(014) ret #262144
(015) ret #0

ይህ ከላይ ያለው ፕሮግራም በመሠረቱ የሚያደርገው ነው.

  • መመሪያ (000): ፓኬጁን በ Offset 12, እንደ ባለ 16-ቢት ቃል, ወደ ማጠራቀሚያው ውስጥ ይጭናል. ማካካሻ 12 ከፓኬቱ ኢተርታይፕ ጋር ይዛመዳል።
  • መመሪያ (001): በክምችት ውስጥ ያለውን ዋጋ ከ 0x86dd ጋር ያወዳድራል, ማለትም, ለ IPv6 የኢተርታይፕ እሴት. ውጤቱ እውነት ከሆነ የፕሮግራሙ ቆጣሪ ወደ መመሪያ (002) ይሄዳል ፣ ካልሆነ ፣ ከዚያ ወደ (006) ይሄዳል።
  • መመሪያ (006): እሴቱን ከ 0x800 (የኢተርአይፕ እሴት ለ IPv4) ያወዳድራል. መልሱ እውነት ከሆነ ፕሮግራሙ ወደ (007)፣ ካልሆነ ወደ (015) ይሄዳል።

እና ስለዚህ የፓኬት ማጣሪያ ፕሮግራሙ ውጤቱን እስኪመልስ ድረስ. ይህ ብዙውን ጊዜ ቡሊያን ነው። ዜሮ ያልሆነ እሴት መመለስ (መመሪያ (014)) ማለት ፓኬጁ ተቀባይነት አግኝቷል ማለት ነው፣ እና ዜሮን መመለስ (መመሪያ (015)) ማለት ፓኬጁ ተቀባይነት አላገኘም ማለት ነው።

BPF ቨርቹዋል ማሽን እና ባይትኮድ በ1992 መገባደጃ ላይ ወረቀታቸው ሲታተም በስቲቭ ማካን እና በቫን ጃኮብሰን ቀርበው ነበር። BSD ፓኬት ማጣሪያ፡ አዲስ አርክቴክቸር ለተጠቃሚ ደረጃ ፓኬት ቀረጻይህ ቴክኖሎጂ ለመጀመሪያ ጊዜ የቀረበው በ 1993 ክረምት በ Usenix ኮንፈረንስ ላይ ነው።

BPF ምናባዊ ማሽን ስለሆነ ፕሮግራሞች የሚሰሩበትን አካባቢ ይገልጻል። ከባይቴኮድ በተጨማሪ የባች ሜሞሪ ሞዴሉን (የጭነት መመሪያዎች በቡድን ላይ በተዘዋዋሪ ተተግብረዋል)፣ መመዝገቢያ (A እና X; accumulator and index records)፣ የጭረት ማህደረ ትውስታ ማከማቻ እና ስውር የፕሮግራም ቆጣሪን ይገልጻል። የሚገርመው፣ BPF ባይት ኮድ በ Motorola 6502 ISA ተቀርጿል። ስቲቭ ማካን በእሱ ውስጥ እንዳስታውስ ጠቅላላ ሪፖርት በሻርክፌስት '11፣ ከሁለተኛ ደረጃ ትምህርታቸው በ Apple II ላይ 6502 መገንባትን ያውቁ ነበር፣ እና ይህ እውቀት የ BPF ባይት ኮድን በመንደፍ ስራው ላይ ተጽዕኖ አሳድሯል።

የBPF ድጋፍ በሊኑክስ ከርነል v2.5 እና ከዚያ በላይ ተተግብሯል፣በዋነኛነት በጄይ ሹሊስት ጥረት ታክሏል። የBPF ኮድ እስከ 2011 ድረስ አልተለወጠም ነበር፣ ኤሪክ ዱማሴት BPF አስተርጓሚውን በጂአይቲ ሁነታ እንዲሰራ በአዲስ መልክ ሲያዘጋጅ (ምንጭ፡ JIT ለፓኬት ማጣሪያዎች). ከዚህ በኋላ ከርነል BPF ባይት ኮድን ከመተርጎም ይልቅ የ BPF ፕሮግራሞችን በቀጥታ ወደ ኢላማው አርክቴክቸር ሊለውጥ ይችላል፡ x86፣ ARM፣ MIPS፣ ወዘተ።

በኋላ, በ 2014, Alexey Starovoitov ለ BPF አዲስ የጂአይቲ ዘዴን አቀረበ. በእርግጥ ይህ አዲስ ጂአይቲ አዲስ BPF ላይ የተመሰረተ አርክቴክቸር ሆነ እና eBPF ተብሎ ይጠራ ነበር። ሁለቱም ቪኤምዎች ለተወሰነ ጊዜ አብረው የኖሩ ይመስለኛል፣ ነገር ግን በአሁኑ ጊዜ የፓኬት ማጣሪያ በ eBPF ላይ በመመስረት ተግባራዊ ይሆናል። በእርግጥ፣ በብዙ የዘመናዊ ሰነዶች ምሳሌዎች BPF eBPF እንደሆነ ይገነዘባል፣ እና ክላሲካል BPF ዛሬ ሲቢፒኤፍ በመባል ይታወቃል።

eBPF ክላሲክ BPF ቨርቹዋል ማሽንን በብዙ መንገዶች ያራዝመዋል፡

  • በዘመናዊ ባለ 64-ቢት አርክቴክቸር መሰረት። eBPF ባለ 64-ቢት መዝገቦችን ይጠቀማል እና የሚገኙትን መመዝገቢያዎች ቁጥር ከ 2 (አክሙሌተር እና ኤክስ) ወደ 10 ይጨምራል። eBPF በተጨማሪ ተጨማሪ ኦፕኮዶችን ይሰጣል (BPF_MOV፣ BPF_JNE፣ BPF_CALL...)።
  • ከአውታረ መረብ ንብርብር ንዑስ ስርዓት ተለይቷል። BPF ከባች መረጃ ሞዴል ጋር ተያይዟል። ለጥቅል ማጣሪያ ጥቅም ላይ ስለዋለ, ኮድ የኔትወርክ ግንኙነቶችን በሚያቀርበው ንዑስ ስርዓት ውስጥ ይገኛል. ሆኖም፣ eBPF ቨርቹዋል ማሽን ከመረጃ ሞዴሉ ጋር የተሳሰረ አይደለም እና ለማንኛውም ዓላማ ጥቅም ላይ ሊውል ይችላል። ስለዚህ፣ አሁን የ eBPF ፕሮግራም ከ tracepoint ወይም kprobe ጋር ሊገናኝ ይችላል። ይህ ለሌሎች የከርነል ንኡስ ስርዓቶች አውድ የኢቢፒኤፍ መሳሪያ፣ የአፈጻጸም ትንተና እና ሌሎች በርካታ የአጠቃቀም ጉዳዮችን መንገድ ይከፍታል። አሁን የኢቢፒኤፍ ኮድ በራሱ መንገድ ይገኛል፡ kernel/bpf።
  • ካርታዎች ተብለው የሚጠሩ ዓለም አቀፍ የውሂብ ማከማቻዎች. ካርታዎች በተጠቃሚ ቦታ እና በከርነል ቦታ መካከል የመረጃ ልውውጥን የሚያነቃቁ ቁልፍ እሴት ማከማቻዎች ናቸው። eBPF በርካታ የካርታ ዓይነቶችን ያቀርባል።
  • ሁለተኛ ደረጃ ተግባራት. በተለይም ጥቅልን እንደገና ለመጻፍ፣ ቼክሰምን ማስላት ወይም ጥቅልን መዝጋት። እነዚህ ተግባራት በከርነል ውስጥ ይሰራሉ ​​እና የተጠቃሚ ቦታ ፕሮግራሞች አይደሉም። እንዲሁም ከ eBPF ፕሮግራሞች የስርዓት ጥሪዎችን ማድረግ ይችላሉ።
  • ጥሪዎችን ጨርስ። በ eBPF ውስጥ ያለው የፕሮግራም መጠን በ4096 ባይት የተገደበ ነው። የጅራት ጥሪ ባህሪው የኢቢፒኤፍ ፕሮግራም ቁጥጥርን ወደ አዲስ eBPF ፕሮግራም እንዲያስተላልፍ እና ይህን ገደብ እንዲያልፍ ያስችለዋል (እስከ 32 ፕሮግራሞች በዚህ መንገድ ሊገናኙ ይችላሉ)።

eBPF፡ ምሳሌ

በሊኑክስ የከርነል ምንጮች ውስጥ ለ eBPF በርካታ ምሳሌዎች አሉ። በናሙናዎች/bpf/ ይገኛሉ። እነዚህን ምሳሌዎች ለማጠናቀር በቀላሉ ያስገቡ፡-

$ sudo make samples/bpf/

ለ eBPF ራሴ አዲስ ምሳሌ አልጽፍም፣ ነገር ግን በናሙናዎች/bpf/ ከሚገኙት ናሙናዎች አንዱን እጠቀማለሁ። የኮዱን አንዳንድ ክፍሎች ተመልክቼ እንዴት እንደሚሰራ እገልጻለሁ። እንደ ምሳሌ, ፕሮግራሙን መርጫለሁ tracex4.

በአጠቃላይ እያንዳንዱ ናሙናዎች / bpf / ሁለት ፋይሎችን ያቀፈ ነው. በዚህ ሁኔታ፡-

  • tracex4_kern.cበከርነል ውስጥ እንደ eBPF ባይትኮድ የሚተገበረውን የምንጭ ኮድ ይዟል።
  • tracex4_user.c፣ ከተጠቃሚ ቦታ የመጣ ፕሮግራም ይዟል።

በዚህ ሁኔታ, ማጠናቀር ያስፈልገናል tracex4_kern.c ወደ eBPF ባይት ኮድ። በአሁኑ ጊዜ በ gcc ለ eBPF ምንም የኋላ ኋላ የለም. እንደ እድል ሆኖ፣ clang የኢቢፒኤፍ ባይት ኮድ ማውጣት ይችላል። Makefile ይጠቀማል clang ለማጠናቀር tracex4_kern.c ወደ ዕቃው ፋይል.

ከላይ የገለጽኩት የ eBPF በጣም አስደሳች ከሆኑት ባህሪያት አንዱ ካርታዎች ናቸው። tracex4_kern አንድ ካርታ ይገልፃል፡-

struct pair {
    u64 val;
    u64 ip;
};  

struct bpf_map_def SEC("maps") my_map = {
    .type = BPF_MAP_TYPE_HASH,
    .key_size = sizeof(long),
    .value_size = sizeof(struct pair),
    .max_entries = 1000000,
};

BPF_MAP_TYPE_HASH በ eBPF ከሚቀርቡት በርካታ የካርድ ዓይነቶች አንዱ ነው። በዚህ ሁኔታ, ሃሽ ብቻ ነው. ማስታወቂያ አስተውለህ ይሆናል። SEC("maps"). SEC የሁለትዮሽ ፋይል አዲስ ክፍል ለመፍጠር የሚያገለግል ማክሮ ነው። በእውነቱ, በምሳሌው ውስጥ tracex4_kern ሁለት ተጨማሪ ክፍሎች ተለይተዋል-

SEC("kprobe/kmem_cache_free")
int bpf_prog1(struct pt_regs *ctx)
{   
    long ptr = PT_REGS_PARM2(ctx);

    bpf_map_delete_elem(&my_map, &ptr); 
    return 0;
}
    
SEC("kretprobe/kmem_cache_alloc_node") 
int bpf_prog2(struct pt_regs *ctx)
{
    long ptr = PT_REGS_RC(ctx);
    long ip = 0;

    // получаем ip-адрес вызывающей стороны kmem_cache_alloc_node() 
    BPF_KRETPROBE_READ_RET_IP(ip, ctx);

    struct pair v = {
        .val = bpf_ktime_get_ns(),
        .ip = ip,
    };
    
    bpf_map_update_elem(&my_map, &ptr, &v, BPF_ANY);
    return 0;
}   

እነዚህ ሁለት ተግባራት ከካርታው ላይ ግቤት እንዲሰርዙ ያስችሉዎታል (kprobe/kmem_cache_free) እና በካርታው ላይ አዲስ ግቤት ያክሉ (kretprobe/kmem_cache_alloc_node). በትላልቅ ፊደላት የተጻፉ ሁሉም የተግባር ስሞች ከተገለጹት ማክሮዎች ጋር ይዛመዳሉ bpf_helpers.h.

የነገር ፋይሉን ክፍሎች ከጣልኩ፣ እነዚህ አዳዲስ ክፍሎች አስቀድመው የተገለጹ መሆናቸውን ማየት አለብኝ፡-

$ objdump -h tracex4_kern.o

tracex4_kern.o: file format elf64-little

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 0000000000000000 0000000000000000 00000040 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 kprobe/kmem_cache_free 00000048 0000000000000000 0000000000000000 00000040 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
2 kretprobe/kmem_cache_alloc_node 000000c0 0000000000000000 0000000000000000 00000088 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
3 maps 0000001c 0000000000000000 0000000000000000 00000148 2**2
CONTENTS, ALLOC, LOAD, DATA
4 license 00000004 0000000000000000 0000000000000000 00000164 2**0
CONTENTS, ALLOC, LOAD, DATA
5 version 00000004 0000000000000000 0000000000000000 00000168 2**2
CONTENTS, ALLOC, LOAD, DATA
6 .eh_frame 00000050 0000000000000000 0000000000000000 00000170 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

አሁንም አላቸው tracex4_user.c, ዋና ፕሮግራም. በመሠረቱ, ይህ ፕሮግራም ዝግጅቶችን ያዳምጣል kmem_cache_alloc_node. እንደዚህ አይነት ክስተት ሲከሰት, ተጓዳኝ eBPF ኮድ ይፈጸማል. ኮዱ የነገሩን IP ባህሪ በካርታ ውስጥ ያስቀምጣቸዋል, እና እቃው በዋናው ፕሮግራም ውስጥ ይዘጋል. ለምሳሌ:

$ sudo ./tracex4
obj 0xffff8d6430f60a00 is 2sec old was allocated at ip ffffffff9891ad90
obj 0xffff8d6062ca5e00 is 23sec old was allocated at ip ffffffff98090e8f
obj 0xffff8d5f80161780 is 6sec old was allocated at ip ffffffff98090e8f

የተጠቃሚ ቦታ ፕሮግራም እና የኢቢኤፍኤፍ ፕሮግራም እንዴት ይዛመዳሉ? ሲጀመር tracex4_user.c የነገር ፋይል ይጭናል tracex4_kern.o ተግባሩን በመጠቀም load_bpf_file.

int main(int ac, char **argv)
{
    struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
    char filename[256];
    int i;

    snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);

    if (setrlimit(RLIMIT_MEMLOCK, &r)) {
        perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)");
        return 1;
    }

    if (load_bpf_file(filename)) {
        printf("%s", bpf_log_buf);
        return 1;
    }

    for (i = 0; ; i++) {
        print_old_objects(map_fd[1]);
        sleep(1);
    }

    return 0;
}

እያደረጉ load_bpf_file በ eBPF ፋይል ውስጥ የተገለጹ መመርመሪያዎች ተጨምረዋል። /sys/kernel/debug/tracing/kprobe_events. አሁን እነዚህን ዝግጅቶች እናዳምጣለን እና ፕሮግራማችን ሲከሰት አንድ ነገር ሊያደርግ ይችላል.

$ sudo cat /sys/kernel/debug/tracing/kprobe_events
p:kprobes/kmem_cache_free kmem_cache_free
r:kprobes/kmem_cache_alloc_node kmem_cache_alloc_node

በናሙና/bpf/ ውስጥ ያሉት ሁሉም ፕሮግራሞች በተመሳሳይ መልኩ የተዋቀሩ ናቸው። ሁልጊዜ ሁለት ፋይሎችን ይይዛሉ:

  • XXX_kern.cኢቢፒኤፍ ፕሮግራም
  • XXX_user.c: ዋና ፕሮግራም.

የኢቢፒኤፍ ፕሮግራም ከክፍል ጋር የተያያዙ ካርታዎችን እና ተግባራትን ይለያል። ከርነሉ የተወሰነ አይነት ክስተት ሲያወጣ (ለምሳሌ፣ tracepoint), የታሰሩ ተግባራት ይፈጸማሉ. ካርዶቹ በከርነል ፕሮግራም እና በተጠቃሚው ቦታ ፕሮግራም መካከል ግንኙነትን ይሰጣሉ.

መደምደሚያ

ይህ መጣጥፍ BPF እና eBPF በጥቅል አነጋገር ተወያይቷል። ስለ ኢቢፒኤፍ ዛሬ ብዙ መረጃ እና ግብዓቶች እንዳሉ አውቃለሁ፣ ስለዚህ ለተጨማሪ ጥናት ጥቂት ተጨማሪ ምንጮችን እመክራለሁ

እንዲያነቡ እመክራለሁ።

ምንጭ: hab.com

አስተያየት ያክሉ