Stuff for Geeks
158 subscribers
181 photos
38 videos
178 files
575 links
Admin: @the_mhbr
Download Telegram
Stuff for Geeks
خب گفتیم که setpgid چندتا نکته و چندتا محدودیت داره. اول نکته هاش رو میگم: - اگه آرگومان اولش صفر باشه، pid پراسسی که تابع رو صدا زده استفاده میشه. ینی اگه بگیم setpgid(0, 100) منظورمون اینه که پراسسی که این تابع رو داره صدا میزنه به پراسس گروپ با pid صد منتقل…
اما سشن
گفتیم که یه سشن مجموعه‌ای از پراسس گروپ‌هاست. وقتی یه پراسس می‌سازیم، سشن آیدیش، سشن آیدی والدش میشه.
هر سشنی یه سشن آیدی از جنس pid_t داره که pid پراسس سازندهٔ اون سشن هست و همه پراسس‌های موجود در یک سشن، یک controling terminal دارن.

با سیستم کال
getsid(pid_t)
می‌تونیم سشن آیدی یه پراسس رو پیدا کنیم و با سیستم کال
setsid()
می‌تونیم یه سشن جدید بسازیم که صدازنندهٔ این تابع میشه سشن لیدر اون سشن و البته سشن جدید هیچ controlling terminalای نخواهد داشت. البته باز نکته‌ها و محدودیت‌هایی داریم اینجا که جلوتر میگم.

قبل از اینکه نکته و محدودیت‌های این تابع رو بگم، یه کاربردش رو بگم.
فرض کنید بخوایم یه پراسس daemon داشته باشیم. یعنی پراسسی که توی پس زمینه داره اجرا میشه، معمولا با روشن شدن کامپیوتر اجرا میشه و با خاموش شدنش بسته میشه و با یوزر هیچ اینترکشنی نداره. یه چیزی خیلی شبیه به یونیت‌های systemd.
اگه بخوایم برناممون یه daemon بشه، یکی از کارهایی که باید انجام بدیم، صدا زدن این تابع setsid هست تا پراسسمون مستقل از هر ترمینالی بشه و سشن خودش رو داشته باشه.

یه محدودیت این تابه که تقریبا باید براتون واضح باشه، اینه که نمیشه برای یه پراسسی که سشن لیدر هست، این تابع رو اجرا کنیم و منتقلش کنیم به یه سشن دیگه. چون در اینصورت، دوتا سشن با آیدی‌های یکسان خواهیم داشت(سشن آیدی، پراسس آیدیِ سشن لیدره). پس این یه محدودیت.

یه نکته هم این که با صدا زدن این تابع، یه سشن جدید و یه پراسس گروپ جدید ساخته میشه که هردوتاشون آیدیشون پراسس آیدیِ پراسس صدا زنندهٔ این تابع هست.

خب با یکم دقت باید محدودیت دوم این تابع رو حدس بزنید.
پراسس صدا زنندهٔ این تابع، نباید پراسس گروپ لیدر باشه. چرا؟ چون در اینصورت، دوتا پراسس گروپ با یه آیدی در دو سشن متفاوت خواهیم داشت که نمیشه.

پس محدودیت‌های تابع اینه که پراسس صدا زننده نباید سشن لیدر یا پراسس گروپ لیدر باشه.

برای اینکه ازین قضیه مطمئن شیم، کافیه قبل از setsid صدازدن، یه
fork()
بزنیم و یه پراسس فرزند بسازیم. چون پراسس فرزند پراسس آیدی جدید خودش رو داره، قاعدتا دیگه سشن لیدر یا پراسس گروپ لیدر نخواهد بود و setsid می‌تونه اجرا شه.

#Linux
#Programming
A very good explanation on different encoding methods used in different versions of the Ethernet protocol:

https://units.folder101.com/cisco/sem1/Notes/ch7-technologies/encoding.htm
سیگنال‌ها در لینوکس
احتمالا با مفهوم سیگنال آشنا باشید. سیگنالها یکی از مکانیزم‌های قدیمی IPC هستن که تو همه سیستم‌عامل‌ها وجود دارن. به سیگنال‌ها وقفه‌های نرم‌افزاری هم گفته میشه. به این معنی که با ورود یک سیگنال به یک پراسس، اگه برنامه اون سیگنال رو بلاک نکرده باشه، instruction pointer هرجا باشه میره توی تابع handler ای که برای سیگنال مربوطه نوشته شده و اون برنامه رو اجرا میکنه و بعد برمی‌گرده سرجای قبلیش و ادامهٔ برنامه اجرا میشه.
این میشه مفهوم کلی سیگنال.

اما بذارید ببینیم توی لینوکس برای کار با این مکانیزم چیا داریم.
خب معروف ترین توابعی که داریم signal و kill هستن. تابع اول یه سیگنال و یه فانکشن پوینتر می‌گیره و باعث میشه برای سیگنال ورودی داده شده بهش، هندلر داده شده اجرا شه.
تابع دوم یا kill همونطور که توی بش هم داریمش، به یه pid یه سیگنال می‌فرسته.
البته که برای استفاده ازین توابع باید هدر signal.h رو اینکلود کنیم.

توجه کنید که وقتی توی یه سیگنال هندلر هستیم، همهٔ سیگنال‌های دیگه بلاک میشن تا موقعی که از سیگنال هندلر خارج شیم. پس خوبه که همیشه سیگنال‌هندلرامون تا جایی که جا داره خلاصه نوشته بشن تا سریع اجراشون تموم شه.

سه تا نکته برای تابع kill داریم.
۱. اگه pid ورودی به این تابع صفر باشه، سیگنال مشخص شده به همهٔ پراسس‌های موجود در پراسس گروپ کسی که تابع رو صدا زده فرستاده میشه. حتی به خود پراسس صدا زنندهٔ این سیستم کال

۲. اگه pid منفی یک باشه، سیگنال مربوطه به همه پراسس‌هایی که پراسس صدازنندهٔ تابع بهشون دسترسی داره، فرستاده میشه البته بجز init و خود پراسس صدا زنندهٔ تابع.

۳. اگه pid کوچیک‌تر از منفی یک باشه، مثلا
-۶۴
سیگنال مشخص‌شده، به همه پراسس‌های موجود در پراسس گروپی با آیدی قدرمطلق پارامتر pid فرستاده میشه. ینی تو این مثال، سیگنال مشخص شده به تمام پراسس‌های پراسس گروپی با آیدی ۶۴ ارسال میشه.



موضوع دیگه اینکه توی لینوکس دو مدل سیگنال داریم. سیگنال‌های real time و سیگنال‌های استاندارد. سیگنال‌های استاندارد که شمارشون از یک شروع و به ۳۱ ختم میشه، صف نمیشن. ینی اگه یه پراسسی یه سیگنالی رو بلاک کرده باشه و صدبار یه سیگنال براش بفرستیم، بعد از آنبلاک کردن سیگنال، فقط یک‌بار اون سیگنال به پراسس فرستاده میشه و هندلرش یکبار صدا زده میشه ولی سیگنال‌های real time صف میشن.

برای تابع signal هم چندتا نکته داریم. اول از همه اینکه signature این تابع به شکل زیره:
sighandler_t signal(int sig, sighandler_t handler)

تایپ sighandler_t که توی glibc تعریف میشه(لازمه که ماکروی
_GNU_SOURCE
رو دیفاین کنیم)، از نوع پوینتر به یه تابعه که اینت میگیره و void برمی‌گردونه.
یعنی تابعی که قراره به عنوان سیگنال هندلر ازش استفاده کنیم، باید یه اینت بگیره و void برگردونه:
void handler(int sig_number){
}

دوتا مسئله اینجا هست. یک اینکه اینتیجر ورودی چیه و دوم اینکه چرا تایپ برگردان تابع باید همچین تابعی باشه؟
جواب سوال اول اینه که این اینتیجر، یه عدده که نشون میده برای بار چندم این سیگنال داره به پراسس ارسال میشه. این عدد شماره سیگنالیه که باعث ورود به این هندلر شده (توجه کنید که میشه چندین سیگنال یه هندلر داشته باشن)
و جواب سوال دوم هم اینه که اون چیزی که تابع برمی‌گردونه، هندلر قبلی این سیگناله که برای ریست کردنِ سیگنال هندلر می‌تونه مفید باشه.

ادامه دارد...

#Linux
#programming
2
Stuff for Geeks
سیگنال‌ها در لینوکس احتمالا با مفهوم سیگنال آشنا باشید. سیگنالها یکی از مکانیزم‌های قدیمی IPC هستن که تو همه سیستم‌عامل‌ها وجود دارن. به سیگنال‌ها وقفه‌های نرم‌افزاری هم گفته میشه. به این معنی که با ورود یک سیگنال به یک پراسس، اگه برنامه اون سیگنال رو بلاک…
سیگنال‌ها در لینوکس
قسمت دوم

تا اینجا kill و signal رو دیدیم. در ادامه، تابع raise رو داریم که یه سیگنال به پراسس صدا زنندش میفرسته. البته دقیق‌تر بخوایم بگیم به ترد صدا زنندش. درواقع سیگنال‌ها به تردها ارسال میشن و نه پراسس‌ها.
سیگنیچر تابع raise خیلی سادست:
raise(int signal)

تابع دیگه‌ای که داریم، killpg هست. این تابع یه سیگنال رو به یه پراسس گروپ می‌فرسته. درواقع دو خط زیر یک کار انجام میدن(به پست قبل رجوع کنید):
killpg(pgid, sig)
signal(-pgid, sig)
اگه آرگومان اول این تابع صفر باشه، سیگنال مشخص‌شده به پراسس گروپ کسی که تابع رو صدا زده ارسال میشه.

و اما یکی از مهم ترین توابعی که داریم sigaction هست. این تابع کارش تنظیم کردن اینه که چجوری پراسس باید به یه سیگنال پاسخ بده(signal deposition)
درواقع نسخهٔ خیلی کامل‌تر تابع signal میشه این تابع.
سیگنیچر این تابع به شکل زیره:
int sigaction(int signal, const struct sigaction * act, const struct sigaction* oldact)

و استراکچر sigaction هم به شکل زیر تعریف شده:
struct sigaction{
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}

اولین فیلد استراکچر فانکشن پوینتر به یه سیگنال هندلره که میتونه آدرس یه تابع، SIG_DFL و یا SIG_IGN باشه. فیلد دومش، sa_mask هست که یه مجموعه سیگنال(sigset_t که بعدا بیش‌تر توضیح میدم) می‌گیره. این مجموعه سیگنال موقعی که توی هندلر باشیم بلاک خواهند شد (خود اون سیگنالی که باعث وارد شدن به اون هندلر شده هم بلاک میشه بطور پیش‌فرض).
و فیلد سوم یه بیت مسکه که یه سری فلگ‌ها رو باهش می‌تونیم برای سیگنالمون تنظیم کنیم. مثلا می‌تونیم تنظیم کنیم که یک سیگنال توی هندلرش خودش رو بلاک نکنه(SA_NODEFER).
یا می‌تونیم تنظیم کنیم بعد از اینکه هندلر اجرا شد، deposition اون سیگنال بشه SIG_DFL و دیگه هندلرما صدا زده نشه براش(SA_RESETHAND) و یه سری موارد دیگه.

فیلد آخر این استراکچر هم برای استفاده‌های داخلیه و برای ما کاربردی نداره.

ادامه دارد...

#Linux
#Programming
🖤🖤🖤🖤🖤
💔6
Stuff for Geeks
C++23 std::expected https://www.cppstories.com/2024/expected-cpp23/ #Programming #cpp
این سایت cppstories کلا خیلی خوبه برای مدرن سی پلاس پلاس
چند الگوریتم مفید در c++

1) std::min_element
با این الگوریتم میتونین کوچیک ترین عضو یه کانتینر رو پیدا کنین
و البته برای مقایسه المنتای کانتینر میتونین یه لامبدا بهش پاس بدین:
std::vector<double> vec;
double min=*std::min_element(vec.cbegin(), vec.cend());

std::vector<MyType> vec2;
MyType min = *std::min_element(vec2.cbegin(), vec2.cend(), [](const MyType& lhs, const MyType& rhs){ return lhs.field1<rhs.field1;});

توجه کنید که این تابع ایترتور برمی‌گردونه و برای همینه که از * استفاده شده.

2) std::max_element
مثل الگوریتم قبلی با این تفاوت که ماکسیمم برمی‌گردونه

3) std::minmax_element
این الگوریتم هردوی مینیمم و ماکسیمم رو با یه std::pair از ایترتورها برمی‌گردونه.

4) std::rotate
این الگوریتم کانتینر اعضای کانتینر رو به یه نحو خاصی جابجا میکنه

ورودی تابع سه تا فوروارد ایترتوره. مثلا
std::rotate(vec.begin(), vec.begin()+3 , vec.end());

با صدا زدن اینجوری این الگوریتم روی کانتینر vec، هرچی المنت قبل vec.begin()+3 باشه میره آخر کانتینر و نتیجتا vec.begin()+3 میشه سر کانتینر جدیدمون.
پس اعضای قبل پارامتر دوم این الگوریتم به آخر الگوریتم منتقل میشن تا این پارامتر بشه اول کانتینرمون

4) std::partition
این الگوریتم دوتا ایترتور برای اول و آخر کانتینرمون میگیره و یه لامبدا یا فانکشن پوینتر که boolean برمی‌گردونه و اعضای کانتینر رو جوری می‌چینه که اون اعضایی تابع براشون true هست میان اول کانتینر و اونایی که false ان میرن آخر کانتینر. البته ترتیب اعضا ممکنه بهم بخوره. مثلا فرض کنین یه وکتور از بولینها مثل زیر داشته باشیم:
0,1,0,1,1
و تابع ورودی به فانکشنمون هم صرفا ترو یا فالس این بولین رو برگردونه. نتیجش این میشه که بعد از اجرای الگوریتم، وکتورمون به شکل زیر تبدیل میشه:
1,1,1,0,0

حالا مشکلی که داره اینه که ممکنه ترتیب المنتها حفظ نشه و خب اگه خواسته باشیم که حتما ترتیب حفظ بشه الگوریتم std::stable_partition رو باید استفاده کنیم.

#Programming
#cpp
Forwarded from OS Internals (Abolfazl Kazemi)
🔍 قابل توجه علاقه‌مندان به امنیت سیستم‌عامل و توسعه اکسپلویت در لینوکس

من همیشه به تدریس علاقه‌مند بوده‌ام؛ نه صرفاً آموزش تئوری، بلکه انتقال واقعی تجربه‌ها و درک عمیق مفاهیم فنی. از سال‌ها پیش، تمرکزم روی internal سیستم‌عامل‌ها—به‌ویژه ویندوز و لینوکس—و مباحث امنیتی بوده و سعی کرده‌ام این مطالب تخصصی را به زبانی ساده، کاربردی و قابل‌فهم برای دیگران ارائه دهم.

🎓 حالا نوبت یک قدم جدید و متفاوت رسیده:
«دوره‌ی Exploit Development در لینوکس»
از تحلیل آسیب‌پذیری‌ واقعی گرفته تا نوشتن اکسپلویت‌های عملی و کاربردی.

اما تصمیم گرفتم یک شرط خاص برای انتشار این دوره بگذارم:
🎯 اگر اعضای کانالم به ۵۰۰۰ نفر برسند، دوره را به صورت کامل و رایگان منتشر می‌کنم.

بیش از ۲۰ ساعت ویدئو و تمرین عملی بدون تبلیغات، بدون پرداخت هزینه—صرفاً برای این‌که دانش تخصصی، راحت‌تر و بی‌واسطه به دست کسانی برسه که واقعاً به یادگیری اهمیت می‌دن.

🧠 اگر شما هم به این مسیر علاقه‌مندید یا فکر می‌کنید افراد دیگری در اطرافتان هستند که این محتوا به دردشان می‌خورد، خوشحال می‌شم با معرفی کانالم به دوستان‌تان از این پروژه حمایت کنید.

📎 لینک کانال:
https://t.iss.one/OxAA55

✍️راستی سرفصل دوره رو هم می‌تونید در لینک زیر مشاهده کنید:
https://t.iss.one/OxAA55/140
کمی اترنت

اترنت اولین بار دوروبر سالای ۱۹۷۵ توسط Xerox توسعه پیدا کرد که به این ورژنش الان Ethernet I میگن و دیگه استفاده هم نمیشه ولی پایهٔ ورژنای بعدیه

چهار پنج سال بعد و حول و حوش سالای ۱۹۸۰ اینتل و یکی دوتا شرکت دیگه از جمله همین Xerox یه مقدار استانداردترش کردن و Ethernet II رو ارائه دادن که الان خیلی استفاده میشه. سرعت اترنت تو این نسخه 10Mbps عه.

و نهایتا بعد یکی دوسال جناب IEEE اترنت رو به عنوان IEEE 802.3 یه مقدار تغییر داد و ثبت کرد.

امروز روز ما بیش تر از Ethernet II استفاده می‌کنیم ولی 802.3 هم استفادش زیاده.

یه سری اکستنشن داشت 802.3 که سرعت رو افزایش داد:
802.3u -> 100Mbps
802.3ab -> copper 1Gbps
802.3z -> fiber 1Gbps
802.3ae -> 10Gbps
...

کدینگ ورژن 10mbps اترنت، Manchester Phase Encoding یا MPE بود. توی این روش کدینگ، به ازای سطح منطقی یک، یه لبه پایین رونده (از حدود ۰.۹ ولت مثبت به منفی) و برای سطح منطقی صفر، یه لبه بالارونده ارسال میشه و اگه خط صفر ولت باشه، معنیش اینه که خط توی حالت idle عه.
توی ورژنای بعدی البته این کدینگ عوض شده. مثلا توی 1Gpbs کدینگمون 4D pam عه. یعنی چهار خط Pam موازی🤯
تو لینک این پست اطلاعات بیش‌تری درمورد کدینگای مختلف اترنت پیدا می‌کنین:
https://t.iss.one/stuff_for_geeks/979


درمورد فرمت فریم اترنت بخوام بگم اینجوریه که اول هفت بایت preamble داریم. درواقع هفت بار یه عدد ثابت(0xAA) رو می‌فرستیم و بعد یه بایت SFD یا start frame delimiter می‌فرستیم که این هم یه عدد ثابته(0xAB).

هدف از فرستادن این هشت بایت صرفا سینک شدن فرستنده و گیرندست و هیچ کاربرد دیگه‌ای نداره و تو همون کارت شبکه استفاده میشه و به بیرون ازش نمیاد کلا.(نمیشه با کارت شبکه‌های عادی کپچرش کرد. لااقل تا جایی که من سرچ کردم)

اما بعد این هشت بایت اصل ماجرا شروع میشه. بعد این هشت بایت، شیش بایت dst address و بعد شیش بایت src address رو داریم که همون مک آدرس مقصد و مبدأمونه.

بعد از این آدرس‌ها یه دوبایت داریم که توی Ethernet II بهش فیلد type میگن و توی 802.3 فیلد length. توی اترنت ورژن دو این دوبایت نشون دهنده اینن که دیتای PDU ای که در ادامه خواهد بود، چه مدلیه. مثلا برای IPv4، این دوبایت میشن 0x8000 و برای IPv6 میشن 0x86DD و برای ARP میشن 0x0806.

بعد این دوبایت ممکنه دوبایت P/Q tag داشته باشیم و ممکنه هم نداشته باشیم. مثلا اگه دوبایتمون 0x8100 باشن، معنیش اینه که این فریم یه Q tagged frame عه و دوبایت Q tag خواهیم داشت.(این قسمت رو ChatGPT با یه مقدار تفاوت گفت و خب ممکنه عوض شده باشه نسبت به چیزی که من خوندم. اگه می‌دونین بگین تا منم از گمراهی بیام بیرون)

در ادامه ممکنه یه سری تگ دیگه هم باشه یا نباشه و بعدش پیلود لایه بالاتر رو داریم که میتونه تا ۲۰۰۰ بایت باشه.
نهایتا هم یدونه CRC32 داریم برای integrity check تا ببینیم دیتا درست منتقل شده یا نه.

پست بعدی یه عکس میذارم از فرمت فریم اترنت
اون قسمتی که گفتم چت جی‌پی‌تی یه چیز دیگه میگه محل قرار گرفتن 802.1Q header بود که توی این عکس که از ویکی‌پدیاست هم با عکس قبلی فرق داره
Stuff for Geeks
کمی اترنت اترنت اولین بار دوروبر سالای ۱۹۷۵ توسط Xerox توسعه پیدا کرد که به این ورژنش الان Ethernet I میگن و دیگه استفاده هم نمیشه ولی پایهٔ ورژنای بعدیه چهار پنج سال بعد و حول و حوش سالای ۱۹۸۰ اینتل و یکی دوتا شرکت دیگه از جمله همین Xerox یه مقدار استانداردترش…
یه سوال دیگه اینجا مطرح میشه که CRC32 چیه و چطوری حساب میشه

خب این مدل فیلدها برای تشخیص خطا بکار میرن مثل هش که برای اینکه بفهمیم یه دیتایی درست جابجا شده یا نه
یعنی کاربردشون صرفا integrity checking عه

البته هش خیلی روش بهتری و دقیق‌تریه به نسبت CRC ولی خب اینم یه چیزه کار راه بندازه

برای محاسبه CRCn یه پیام، به یه عدد موسوم به چندجمله‌ای مولد (generator polynomial) نیاز داریم که طولش n+1 عه و الگوریتم محاسبش هم اینه:
به انتهای پیام به تعداد n صفر اضافه می‌کنیم و باقی مانده این عدد جدید رو به چند جمله‌ای مولدمون می‌گیریم. نهایتا مکمل یک این باقی‌مانده میشه CRCn ما.
مکمل یک هم اینه که همه بیت‌ها رو برعکس کنیم(صفرها رو یک و یک‌ها رو صفر کنیم).

خب مشخصه که چون داریم صرفا باقی‌مانده می‌گیریم، مثل هش یه تابع یک به یک نداریم و به همین دلیله که این روش عالی نیست هرچند که چون طول چندجمله‌ای مولدمون سی و دو بیته، با انتخاب بهینش واقعا نتایج خوبی می‌گیریم.


توی اترنت فریم فیلد آخرمون CRC32 کل فریم اترنت به جز منطقا خودشه یعنی از src address تا آخر پیلود.

فک کنم واضحه که گیرنده که فریم اترنت رو میگیره دوباره CRC رو حساب می‌کنه و اگه با CRC موجود توی فریم دریافتیش یکی نبود، می‌فهمه که اشتباه پیام رو گرفته.
اترنت و شبکه محلی مجازی(VLAN)
همونطور که احتمالا می‌دونید، یه مفهومی به اسم لن مجازی یا 802.1q داریم که به ما اجازه میده توی سوئیچ‌هامون شبکمون رو قسمت بندی کنیم بدون اینکه فیزیکی شبکه رو جدا جدا کنیم. توی این پست میخوام درمورد اینکه چجوری این قابلیت تو سطح اترنت رخ میده صحبت کنم.

خب شما توی کنسول سوئیچ وارد میشید و تعریف میکنید که فلان پورت‌ها با هم یه لن مجازی تشکیل بدن.

تو این سناریو هاست ها یا station ها هیچ تغییری نکردن پس فریم اترنتی که از سمتشون میاد هم هیچ تغییری نخواهد کرد و مثل همون چیزی خواهد بود که توی پست‌های قبل‌تر گفتیم.
درواقع یه station فریمش رو می‌فرسته و سوئیچ که می‌دونه از کدوم پورت این فریم واردش شده، طبق جداول vlanای که داره تصمیم می‌گیره این فریم رو به کجا بفرسته اما اینجا یه نکته هست که باعث شد 802.1q بوجود بیاد.
فرض کنید لن مجازیمون فقط به یک سوئیچ محدود نباشه و مثلا بین دو یا چندتا سوئیچ پخش شده باشه.

اینجا باید فریمی که بین سوئیچ‌ها منتقل میشه مشخص باشه مال کدوم لن مجازیه. یعنی نمیشه شما یه فریم مال vlan1 داشته باشی و موقعی که داری میفرستیش برای سوئیچ دومت نگی این مال کدوم vlanعه. خب واضحه که نمیشه.

برای همین به فریم اترنتمون یه تگ اضافه می‌کنیم به اسم تگ 802.1q که دقیقا توش مشخص کردیم این فریم مال کدوم vlanعه. این تگ بعدا قبل اینکه برسه به استیشن مقصد توسط سوئیچ پاک میشه.
به این کار که ترافیک چند vlan رو از یه کانال عبور بدیم، trunking هم میگن(شاید مفهوم دقیق تری داشته باشه ولی من همینقدر می‌دونم)

البته باید سوئیچ کانفیگ بشه و براش تعریف بشه که کدوم پورتش به یه سوئیچ دیگه داره وصل میشه و برای این پورتش trunking ست بشه.

همونطور که توی عکسای قبلی مشخصه، به فریممون یه p/q tag اضافه میشه که یکی از بخشاش دوازده بیت VIDعه که نشون میده می‌تونیم تا 2^12 یا 4096 تا vlan تعریف کنیم(البته VID نمیتونه صفر و 4095 باشه که دوتا از مجموع تعداد vlan های قابل تعریف کم میکنه)

توی هدر 802.1q یه سه تا بیت بعد از tag id داریم که بهش priority code pin یا PCP هم میگن و این قسمت میشه بخش 802.1p مون. این سه تا بیت طبق استاندارد مشخص کننده اینن که این فریم چقدر اولویت داره و آیا باید زودتر از بقیه فریم‌ها منتقل بشه یا نه.

البته اینکه هر مقدار مشخص از این سه بیت چه معنایی بده رو استاندارد تعریف نمیکنه و دست سازنده‌ها رو باز می‌ذاره. مثلا رایجه که برای VoIP که لیتنسی کم مدنظره، این مقدار PCP عدد شیش باشه.

پ.ن: سورس این چند پست اخیر کتابیه که 2011 چاپ شده و ممکنه یه مقدار استانداردا عوض شده باشن.

پ.ن۲: شبکه رو تازه شروع کردم و ممکنه اشتباه داشته باشه توضیحاتم
Stuff for Geeks
اون قسمتی که گفتم چت جی‌پی‌تی یه چیز دیگه میگه محل قرار گرفتن 802.1Q header بود که توی این عکس که از ویکی‌پدیاست هم با عکس قبلی فرق داره
اترنت و MTU

اگه یبار دیگه به فریم اترنت نگاه کنیم، می‌بینیم که یه بخشی به اسم پیلود داریم. این بخش میتونه از ۴۶ بایت تا ۱۵۰۰ بایت یا جدیدا ۲۰۰۰ بایت توی نسخه‌ی استاندارد اترنت باشه. یه اکستنشن اترنتی به اسم jumbo frame هم داریم که اجازه میده تا ۹۰۰۰ و خورده‌ای بایت برسیم. به این سایز MTU یا Maximum Transmission Unit گفته میشه.

کم بودن MTU باعث میشه زیادی CRC بگیریم و چک کنیم که خب خوب نیست ولی زیاد بزرگ بودنش هم باعث میشه اگه فریم خراب بشه، یه حجم بزرگی از دیتا دوباره ارسال شه که بازم خوب نیست.

توی گنوم می‌تونین دستی mtu اینترفیستون رو تنظیم کنین و خب با nmcli و iproute هم قاعدتا میشه. مثلا با iproute داریم:
ip link set dev eth0 mtu 9000

پ.ن: یه extreme jumbo frame هم داریم که اجازه میده mtu بزرگتر از این حرفا باشه ولی NIC های خاص می‌خواد