পাঠ ৪৪ · ৫৭-এর মধ্যে · মডিউল ৯
Home / Courses / Computer Networks / QoS মেকানিজম

QoS মেকানিজম

QoS mechanisms
৭ মিনিট পড়া মধ্যবর্তী · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • কেন সব ট্রাফিককে একইভাবে ট্রিট করা (best-effort) সবসময় যথেষ্ট নয়
  • ট্রাফিক ক্লাসিফিকেশন ও মার্কিংয়ের ধারণা
  • Priority Queuing বনাম Weighted Fair Queuing — এদের ট্রেড-অফ
  • একটি Weighted Fair Queuing শিডিউলার বাস্তবে বাস্তবায়ন করে দেখা যে শেয়ার সত্যিই ওজন অনুযায়ী বণ্টন হয়

১ · কেন QoS দরকার

ইন্টারনেটের ঐতিহাসিক ডিফল্ট মডেল হলো best-effort — প্রতিটি প্যাকেট সমানভাবে ট্রিট হয়, কোনো অগ্রাধিকার নেই, রাউটার যতটুকু পারে তত দ্রুত ফরওয়ার্ড করার "সর্বোচ্চ চেষ্টা" করে। কিন্তু বাস্তবে বিভিন্ন অ্যাপ্লিকেশনের প্রয়োজন ভিন্ন — একটি ভয়েস কল লেটেন্সি ও জিটারের (M9/L42) প্রতি অত্যন্ত স্পর্শকাতর (সামান্য দেরিও শ্রুতিগোচর সমস্যা তৈরি করে), কিন্তু একটি ব্যাকগ্রাউন্ড ফাইল ডাউনলোড কয়েক সেকেন্ড দেরি হলেও ব্যবহারকারী টেরই পাবেন না। যখন এই দুই ধরনের ট্রাফিক একই সীমিত ব্যান্ডউইথের জন্য প্রতিযোগিতা করে, best-effort মডেলে ভয়েস কলও ফাইল ডাউনলোডের মতোই কিউতে অপেক্ষা করে — এতে কলের মান খারাপ হতে পারে। QoS মেকানিজম এই সমস্যা সমাধান করে বিভিন্ন ট্রাফিককে ভিন্নভাবে অগ্রাধিকার দিয়ে।

২ · ট্রাফিক ক্লাসিফিকেশন ও মার্কিং

QoS প্রয়োগ করতে প্রথমে প্রতিটি প্যাকেটকে একটি ট্রাফিক ক্লাসে শ্রেণীবদ্ধ করতে হয় (যেমন "ভয়েস," "ভিডিও কনফারেন্সিং," "বাল্ক ডেটা")। এই শ্রেণী সাধারণত IP হেডারের DSCP (Differentiated Services Code Point) ফিল্ডে মার্ক করা হয় (শুধু উল্লেখমাত্র, বিস্তারিত নয়) — পথের প্রতিটি রাউটার এই মার্কিং দেখে প্যাকেটটিকে কীভাবে ট্রিট করবে তা সিদ্ধান্ত নেয়, প্রতিবার নতুন করে ক্লাসিফাই না করেই।

৩ · কিউয়িং ডিসিপ্লিন — Priority Queuing বনাম Weighted Fair Queuing

একবার ট্রাফিক শ্রেণীবদ্ধ হলে, রাউটারকে সিদ্ধান্ত নিতে হয় কোন ক্লাসের প্যাকেট আগে সার্ভ করবে। দুটি সাধারণ পদ্ধতি —

Priority Queuing
সর্বোচ্চ-অগ্রাধিকার কিউ সবসময় প্রথমে সম্পূর্ণ সার্ভ হয়, তারপরই পরের কিউ ধরা হয়। সরল, কিন্তু ভারী লোডে নিম্ন-অগ্রাধিকার ট্রাফিক পুরোপুরি "স্টার্ভ" (অনির্দিষ্টকাল বঞ্চিত) হয়ে যেতে পারে।
Weighted Fair Queuing (WFQ)
প্রতিটি ক্লাসকে একটি নির্ধারিত ওজন দেওয়া হয় — প্রতিটি ক্লাস তার ওজনের অনুপাতে একটি গ্যারান্টিড ন্যূনতম শেয়ার পায়, কোনো ক্লাসই সম্পূর্ণ বঞ্চিত হয় না, তবু উচ্চ-ওজন ক্লাস বেশি অগ্রাধিকার পায়।
মূল অন্তর্দৃষ্টি

Priority Queuing-এর ঝুঁকি হলো: যদি উচ্চ-অগ্রাধিকার ট্রাফিক (যেমন ভয়েস) ক্রমাগত আসতে থাকে, নিম্ন-অগ্রাধিকার ট্রাফিক (যেমন ইমেইল) কখনো সার্ভিসই নাও পেতে পারে — এটি "স্টার্ভেশন।" WFQ এই সমস্যা এড়ায় প্রতিটি ক্লাসকে একটি ন্যূনতম গ্যারান্টিড শেয়ার দিয়ে, তাই এটিই আজকের বাস্তব রাউটারে বেশি ব্যবহৃত পদ্ধতি।

নিচের কোডে একটি deficit-counter-ভিত্তিক WFQ শিডিউলার বাস্তবায়ন করা হয়েছে — প্রতিটি রাউন্ডে প্রতিটি ক্লাসের "deficit" কাউন্টারে তার ওজন যোগ হয়; সবচেয়ে বেশি deficit-ওয়ালা (পেন্ডিং প্যাকেটসহ) ক্লাস সার্ভ হয়, এবং তার deficit থেকে মোট ওজন বিয়োগ করা হয়। বহু রাউন্ড ধরে চালালে প্রতিটি ক্লাস ঠিক তার ওজনের অনুপাতে সার্ভিস পায় — এটি নিচের প্রিন্ট আউটে সরাসরি যাচাই করা হয়েছে।

Python
# Weighted Fair Queuing (WFQ) -- deficit-counter ভিত্তিক শিডিউলার
weights = {"voice": 4, "video": 3, "bulk": 1}
total_weight = sum(weights.values())

# প্রতিটি ক্লাসে যথেষ্ট পেন্ডিং প্যাকেট রাখা হয়েছে যাতে সিমুলেশন চলাকালীন কোনো ক্লাস খালি না হয়ে যায়
pending = {cls: [f"{cls}-pkt-{i}" for i in range(100)] for cls in weights}
deficit = {cls: 0 for cls in weights}
service_count = {cls: 0 for cls in weights}

def schedule_next(pending_by_class, weights, deficits):
    """প্রতিটি (পেন্ডিং থাকা) ক্লাসের deficit-এ তার weight যোগ হয়; সর্বোচ্চ deficit-ওয়ালা
    ক্লাস সার্ভ হয়, তারপর তার deficit থেকে মোট weight বাদ যায় -- এই সাধারণ নিয়ম বহু রাউন্ডে
    প্রতিটি ক্লাসকে তার ওজন অনুপাতে সার্ভিস দেয়।"""
    for cls in weights:
        if pending_by_class[cls]:
            deficits[cls] += weights[cls]
    eligible = [c for c in weights if pending_by_class[c]]
    if not eligible:
        return None
    chosen = max(eligible, key=lambda c: deficits[c])
    deficits[chosen] -= sum(weights.values())
    return chosen

ROUNDS = 80
for _ in range(ROUNDS):
    chosen = schedule_next(pending, weights, deficit)
    pending[chosen].pop(0)
    service_count[chosen] += 1

print(f"{ROUNDS} শিডিউলিং রাউন্ডের পর প্রতিটি ক্লাস কতবার সার্ভ হলো:\n")
for cls, w in weights.items():
    expected_share = w / total_weight
    actual_share = service_count[cls] / ROUNDS
    print(f"  {cls:6s} (weight={w}):  served {service_count[cls]:3d} বার  "
          f"->  actual share={actual_share:.3f},  expected share={expected_share:.3f}")

    
লক্ষ্য করুন — voice (weight=৪) মোট ৮০ রাউন্ডের মধ্যে ৪০ বার, video (weight=৩) ৩০ বার, ও bulk (weight=১) ১০ বার সার্ভ হয় — ঠিক ৪:৩:১ অনুপাত (মোট weight=৮, তাই শেয়ার যথাক্রমে ০.৫০, ০.৩৭৫, ০.১২৫)। কোনো ক্লাসই শূন্যবার সার্ভ হয়নি — এটিই WFQ-এর "কোনো ক্লাস সম্পূর্ণ স্টার্ভ হয় না" গ্যারান্টির বাস্তব প্রমাণ।
মূল কথা · Key takeaway

QoS কোনো ট্রাফিককে "দ্রুততর ইন্টারনেট" দেয় না — এটি সীমিত ব্যান্ডউইথকে বিভিন্ন প্রয়োজনের মধ্যে বুদ্ধিমত্তার সাথে বণ্টন করে। M9/L43-এর কিউয়িং থিওরির গণিত ব্যাখ্যা করে *কেন* কিউ ও ডিলে তৈরি হয়; QoS মেকানিজম ব্যাখ্যা করে সেই সীমিত রিসোর্স *কাকে কতটা* দেওয়া হবে তার সিদ্ধান্ত কীভাবে নেওয়া হয়।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ একটি অফিস নেটওয়ার্কে যদি Priority Queuing ব্যবহার করা হয় এবং ভয়েস ট্রাফিক সবসময় সর্বোচ্চ অগ্রাধিকার পায়, তাহলে কী সমস্যা হতে পারে?

যদি ভয়েস কলের ট্রাফিক ক্রমাগত/ভারী থাকে (যেমন একসাথে অনেক কল চলছে), তাহলে নিম্ন-অগ্রাধিকার ট্রাফিক (যেমন ইমেইল সিঙ্ক, ফাইল ডাউনলোড) সম্পূর্ণ "স্টার্ভ" হয়ে যেতে পারে — কখনোই সার্ভিস না পেয়ে অনির্দিষ্টকাল কিউতে আটকে থাকতে পারে, যতক্ষণ না উচ্চ-অগ্রাধিকার কিউ পুরোপুরি খালি হয়। এটিই Priority Queuing-এর মূল ঝুঁকি।

প্র ০২ WFQ-তে একটি ক্লাসের ওজন বাড়ালে অন্য ক্লাসগুলোর শেয়ারে কী প্রভাব পড়বে?

যেহেতু প্রতিটি ক্লাসের শেয়ার হলো তার ওজন ÷ সব ওজনের যোগফল, একটি ক্লাসের ওজন বাড়ালে মোট ওজনের যোগফলও বেড়ে যায়, ফলে বাকি সব ক্লাসের আপেক্ষিক শেয়ার কমে যাবে (যদিও তাদের ওজন নিজে অপরিবর্তিত থাকে) — এটি একটি শূন্য-সমষ্টি (zero-sum) বণ্টন, একজনের বেশি পাওয়া মানে অন্যদের তুলনামূলকভাবে কম পাওয়া।

প্র ০৩ QoS কি ইন্টারনেটের সামগ্রিক ব্যান্ডউইথ বাড়িয়ে দেয়?

না। QoS মোট ব্যান্ডউইথ এক বিটও বাড়ায় না — এটি শুধু সীমিত, বিদ্যমান ব্যান্ডউইথ বিভিন্ন ট্রাফিক ক্লাসের মধ্যে কীভাবে বণ্টন করা হবে তা নিয়ন্ত্রণ করে। যদি মোট চাহিদা লিংকের ক্ষমতার চেয়ে অনেক বেশি হয়ে যায়, QoS শুধু নিশ্চিত করে *কে* বেশি কষ্ট পাবে, সমস্যাটাই দূর করে না — প্রকৃত সমাধান হলো ক্যাপাসিটি বাড়ানো।

অনুশীলন

  1. চিন্তা করুন: আপনার বাসার রাউটারে "Gaming Mode" বা "QoS" সেটিংস অপশন থাকতে পারে — এটি সাধারণত কী করে বলে মনে হয়?

    এই ধরনের রাউটার ফিচার সাধারণত গেমিং/ভিডিও কল ট্রাফিককে বেশি ওজন বা অগ্রাধিকার দেয় (এই লেসনের WFQ বা priority queuing-এর একটি সরলীকৃত ঘরোয়া সংস্করণ), যাতে অন্য ডিভাইস ভারী ডাউনলোড চালালেও গেম/কলের লেটেন্সি ও জিটার কম থাকে — মোট ব্যান্ডউইথ না বাড়িয়েই।

  2. পরীক্ষা করুন: উপরের কোড সেলে weights ডিকশনারিতে bulk-এর ওজন ১ থেকে বাড়িয়ে ৪ করুন (voice ও video অপরিবর্তিত রেখে) এবং দেখুন প্রতিটি ক্লাসের শেয়ার কীভাবে বদলায়।

    নতুন মোট ওজন হবে ৪+৩+৪=১১। voice-এর শেয়ার ৪/১১≈০.৩৬৪-এ নেমে আসবে (আগে ০.৫০ ছিল), video ৩/১১≈০.২৭৩-এ (আগে ০.৩৭৫), আর bulk বেড়ে ৪/১১≈০.৩৬৪-এ যাবে (আগে মাত্র ০.১২৫)। এটি সরাসরি দেখায় ওজন বাড়ানো কীভাবে একটি ক্লাসের প্রকৃত সার্ভিস শেয়ার সরাসরি বাড়িয়ে দেয়, বাকি সবার আপেক্ষিক শেয়ার কমিয়ে।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
কিউয়িং থিওরি বেসিকস