Foundationপ্রথম নীতি থেকে
LEVEL 7লেসন ৫/২২অ্যাডভান্সড১ ঘণ্টা

IPv4 Addressing, Subnetting, CIDR — ঠিকানার গণিত

IPv4 Addressing and CIDR

ইন্টারনেটের address-book-এর গণিত — binary fluency থেকে classful-যুগের অপচয়, CIDR-এর বিপ্লব, subnet-splitting-এর হাতে-কলমে walkthrough, আর aggregation-এ যে সঞ্চয়ে আজকের routing table টিকে আছে।

এই লেসন শেষে আপনি পারবেন

  • Dotted-decimal আর 32-bit binary-র মধ্যে octet-weight (128/64/32/16/8/4/2/1) দিয়ে চোখের ইশারায় রূপান্তর করতে পারবেন
  • Classful যুগের address-waste-এর গল্প বলে CIDR (1993) কেন অনিবার্য হয়েছিল — prefix notation আর netmask-এর bit-level সমতা দেখাতে পারবেন
  • যেকোনো ip/prefix-এর network address, broadcast address, first/last host আর usable host count 2^(32−n)−2 AND-operation দিয়ে হাতে বের করতে পারবেন
  • /24-কে দুইটা /25-এ ভাঙার bit-level walkthrough করে VLSM-পদ্ধতিতে ভিন্ন মাপের multi-subnet plan বানাতে পারবেন
  • RFC1918 private range, loopback, link-local ঠিক চিনতে পারবেন আর route aggregation কীভাবে global routing table ছোট রাখে সংখ্যা দিয়ে ব্যাখ্যা করতে পারবেন

আগে যা বোঝা থাকা দরকার

আগে এটা বুঝি

ip-datagram লেসনে আমরা IP header-এর ভেতরে ঢুকেছিলাম — TTL, protocol, checksum সব দেখেছি। কিন্তু ওই header-এর দুটো field আমরা প্রায় বিনা অনুসন্ধানে পার করে এসেছি: source address আর destination address। 192.168.1.20 → 93.184.216.34 — চার-চারটা সংখ্যা, মাঝে দাগ। এত সরল দেখায়, তাই না?

আজ সেই সরলতার ভেতরে হাত দিয়ে দেখব একটা ৩০ বছরের গল্প — যে ঠিকানা-ব্যবস্থা শুরুতে এতটাই উদারভাবে address বিলিয়েছিল যে ৩০ বছরের মাথায় ইন্টারনেট ঠিকানা ফুরিয়ে যাওয়ার পথে এগোচ্ছিল, আর একটা গণিতের কৌশল — CIDR — কীভাবে সেই বিপর্যয় থেকে পুরো ইন্টারনেটকে টেনে তুলল।

আজকের লেসনের প্রতিশ্রুতি:

  • Dotted decimal আর binary-র মধ্যে দ্রুত দুলুনি — কোনো calculator ছাড়াই
  • Network address, broadcast, host-range: তিনটাই হাতে বের করা
  • একটা subnet-কে ছোট ছোট subnet-এ ভাঙার bit-level walkthrough
  • Private address, loopback, link-local — কোনটা কোথায় বৈধ
  • আর aggregation-এর সেই জাদু, যা ছাড়া আজকের routing table- গুলো গিগাবাইট আকারে ফুলে উঠত

শেষ পর্যন্ত আপনি নিজের হাতে একটা subnet calculator লিখবেন — যার core গণিত আপনি এতক্ষণে মুখস্থ স্তরে বুঝে ফেলবেন। চলুন শুরু করি সবচেয়ে ছোট ইউনিট থেকে: একটা মাত্র bit।

মূল ধারণা

ঠিকানাটা আসলে ৩২টা বাতি

IPv4 address মানে মূলত ৩২টা bit — চালু-বন্ধের ৩২টা switch। Machine দেখে শুধু এই ৩২টা bit; dotted decimal (192.168.1.20) আমাদের মানুষের সুবিধার জন্য বানানো পোশাক। ঐতিহ্য অনুযায়ী ৩২টা bit-কে চারটা ভাগে ভাগ করা হয় — প্রতি ভাগে ৮টা bit, এক-একটা byte, আর প্রতিটা byte-কে 0–255-এর decimal সংখ্যায় লেখা হয়।

৮টা bit-এর প্রতিটার একটা নির্দিষ্ট ওজন আছে — বাঁ দিক থেকে দ্বিগুণ হতে হতে যায়:

| Bit position | ১ম | ২য় | ৩য় | ৪র্থ | ৫ম | ৬ষ্ঠ | ৭ম | ৮ম | |---|---|---|---|---|---|---|---| | Weight | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |

এই আটটা weight মুখস্থ হলেই রূপান্তর মনে-মনে করা যায়। উদাহরণ: 192 = 128 + 64 = 11000000; 168 = 128 + 32 + 8 = 10101000; 20 = 16 + 4 = 00010100। পুরো ঠিকানা:

192     .168     .1      .20
11000000 10101000 00000001 00010100

উল্টো দিকেও একই নিয়ম: 10101000 দেখলে সরাসরি পড়ুন 128+32+8=168।

Netmask — কোন bit কার

একটা IPv4 ঠিকানার ভেতরে দুইটা অংশ লুকানো আছে: network অংশ (কোন পাড়ায় থাকেন) আর host অংশ (পাড়ার কোন বাড়ি)। এই দুই অংশের সীমারেখা টানে সেই পরিচিত সংখ্যা — netmask:

IP       192.168.1.20     11000000 10101000 00000001 00010100
Netmask  255.255.255.0    11111111 11111111 11111111 00000000
         ─────────────    ────────────────┬─────────────────
         network part                host part

Mask-এ যেখানে bit 1, ঠিকানার সেই bit network-এর; mask-এর 0-এর জায়গায় host। এই নির্দিষ্ট mask-এর আরেকটা নাম — /24: বাঁ দিকের ২৪টা bit network-অংশ। Prefix লেখা আর netmask লেখা একই কথা:

PrefixNetmask (decimal)Mask-এর শেষ octet (binary)
/8255.0.0.000000000
/16255.255.0.000000000
/20255.255.240.011110000
/24255.255.255.000000000
/25255.255.255.12810000000
/26255.255.255.19211000000
/30255.255.255.25211111100

তিনটা গুরুত্বপূর্ণ ঠিকানা প্রতিটা subnet-এর

একটা ip/prefix-কে তিনটা প্রশ্ন করা যায়, আর উত্তর তিনটাই AND-operation দিয়ে আসে:

  1. Network address — এই subnet-এর নামফলক: ip AND mask
  2. Broadcast address — subnet-এর সবাইকে একসাথে ডাকার ঠিকানা: host-bit সবগুলো 1
  3. Usable host range — মাঝের যত ঠিকানা সত্যিকারের device নিতে পারে: network+1 থেকে broadcast−1

Host-bit-এর সংখ্যা 32 − prefix হলে মোট host-bit-pattern 2^(32−prefix)-টা, যার প্রথমটা network, শেষটা broadcast — তাই ব্যবহারযোগ্য:

usable=2(32−n)−2\text{usable} = 2^{(32-n)} - 2

Concrete উদাহরণ — 192.168.1.20/24:

Network:    192.168.1.0     (ip AND mask → host-bits সব 0)
Broadcast:  192.168.1.255   (host-bits সব 1)
First host: 192.168.1.1
Last host:  192.168.1.254
Usable:     2^8 − 2 = 254

Classful যুগ — উদারতার দাম

1981-এর মূল ডিজাইনে (RFC 791) ঠিকানার প্রথম কয়েকটা bit-ই বলে দিত সীমারেখা কোথায় — তিনটা fixed শ্রেণি:

শ্রেণিপ্রথম bitsRangePrefixNetworksHosts/network
A0…0–127/812616,777,214
B10…128–191/1616,38465,534
C110…192–223/242,097,152254

সমস্যাটা কল্পনা করুন: আপনার office-এ ৩০০টা computer। Class C দেয় ২৫৪টা — কম! তাহলে নিতে হয় Class B — ৬৫,৫৩৪টা ঠিকানার একটা block, যার ব্যবহার হচ্ছে ৩০০। ৯৯.৫% নষ্ট। আর ছোট organization- গুলো যদি কয়েকশো Class C নেয়, global router-দের টেবিলে তা হাজার হাজার আলাদা লাইন হয়ে জমে — 1990-এর গোড়ায় routing table-এর বৃদ্ধি এমন গতিতে উঠছিল যে projection বলছিল কয়েক বছরেই router-দের memory শেষ।

CIDR — সীমারেখাকে মুক্তি দিয়ে দেওয়া

1993-এ সমাধান এলো (RFC 1519, পরে RFC 4632): Classless Inter-Domain Routing। ভাবটা এতটাই সরল যে প্রথমবার পড়লে হতাশ লাগে — “যেখানে দরকার, ঠিক তত bit-ই network-part ধরা যাক”। প্রথম bits আর তিনটা শ্রেণির নিয়ম বাতিল; এখন প্রতিটা route-এর সাথেই explicit prefix (/n) লেখা লাগে। ফলাফল:

  • ৩০০-host organization নেয় /23 (৫১০ host) — waste মাত্র ২১০
  • ISP তার গ্রাহকদের পাশাপাশি ঠিকানা দিলে সেগুলো একটা prefix-এ bundle করে announce করতে পারে — এটাই route aggregation
  • শ্রেণি-নির্ভর hardware/software-এর যুগ শেষ — সবখানে এখন longest-prefix-match engine (routing লেসনে বিস্তারিত)

CIDR ঠিকানা-অপচয় কমিয়েছে আর routing table ছোট রেখেছে — দুইটা সংকট এক ধাক্কায়। এই দ্বিতীয়টার হিসাবটা under-the-hood অংশে সংখ্যা দিয়ে দেখব।

বিশেষ ঠিকানাগুলো চেনা

সব ৩২-bit সংখ্যাই সাধারণ host নয়। এই তালিকাটা চোখে বসানো মূল্যবান — ip addr বা router config-এর সামনে বসলেই কাজে লাগবে:

Rangeনামকাজ
0.0.0.0/8this-network0.0.0.0 = unspecified/default route
10.0.0.0/8RFC1918 privateভেতরের network, ১.৬ কোটি ঠিকানা
127.0.0.0/8loopbackপুরো /8-ই নিজের দিকে ঘুরে আসে
169.254.0.0/16link-localDHCP ব্যর্থ হলে self-assigned
172.16.0.0/12RFC1918 private172.16–172.31, ~১০ লাখ ঠিকানা
192.168.0.0/16RFC1918 privateবাড়ির router-এর প্রিয়
100.64.0.0/10CGNAT sharedcarrier-grade NAT (nat লেসনে)
224.0.0.0/4multicastএক-থেকে-গোষ্ঠী পাঠানো
240.0.0.0/4reservedexperimental/ব্যবহার-নিষিদ্ধ
255.255.255.255limited broadcastএই link-এর সবাই

RFC1918-এর তিনটা range-ই ইচ্ছেমতো যেকোনো ব্যক্তিগত network-এ ব্যবহারযোগ্য — কারণ এগুলো ইন্টারনেটে route করা হয় না। আপনার বাড়ির 192.168.1.20 আর প্রতিবেশীর 192.168.1.20 একই ঠিকানা — দোষ কিছু নেই, কারণ কেউই সরাসরি ইন্টারনেটে পৌঁছায় না। কীভাবে তাহলে বাইরে যায়? NAT — আজকের শেষ অংশের preview, পূর্ণ লেসন কয়েক ধাপ পরে।

ভেতরে কী ঘটছে

AND-operation — হার্ডওয়্যার আসলে কী করে

Textbook বলে “network address = ip AND mask”। এই AND-টা ভেতরে কী করে, bit-level-এ দেখুন:

  IP    172.16.37.99   10101100 00010000 00100101 01100011
  Mask  /21            11111111 11111111 11111000 00000000
  AND   ───────────    10101100 00010000 00100000 00000000
                       = 172.16.32.0

প্রতিটা column-এ দুটো bit-ই 1 হলে ফল 1, নইলে 0। ফলাফলে লক্ষ্য করুন: প্রথম ২১ bit ঠিকানার হুবহু copy, শেষ ১১ bit সব শূন্য। AND আসলে mask-এর 1-গুলো দিয়ে ঠিকানার অংশ কেটে নেওয়া, বাকিটা মুছে দেওয়া। Broadcast তার দর্পণ-প্রতিবিম্ব: host-bit-গুলো OR দিয়ে সব 1 করা — 172.16.39.255।

এখান থেকেই একটা shortcut: prefix n-এর host-part যদি তৃতীয় octet-এর ভেতরে থাকে (যেমন /21), network-এর ওই octet = own_octet AND mask_octet, আর broadcast = network + (2^host_bits − 1)। হিসাবটা octet-এ সীমাবদ্ধ রাখলে মনে-মনেই চলে।

Subnet splitting — /24 ভাঙুন দুই /25

Borrowing-এর মূল ভাব: host-part-এর প্রথম bit-টা কেড়ে নিয়ে network-part-এ যোগ করা। /24-এ host-part ছিল শেষ octet-এর ৮ bit; এক bit কেড়ে নিলে /25 — এবং সেই bit-এর মান (0 বা 1) বলে দেয় কোন অর্ধেক:

মূল:  192.168.1.0/24        host-part: xxxxxxxx (৮ bit)

ভাঙা: 192.168.1.0/25         0xxxxxxx → 0–127
      └─ borrowed bit = 0
      192.168.1.128/25       1xxxxxxx → 128–255
      └─ borrowed bit = 1

দুই অর্ধেকের হিসাব সাজানো করে দেখি:

Subnet A (/25)Subnet B (/25)
Network192.168.1.0192.168.1.128
First host192.168.1.1192.168.1.129
Last host192.168.1.126192.168.1.254
Broadcast192.168.1.127192.168.1.255
Usable2^7−2 = 126126

একই পদ্ধতি চালিয়ে যেকোনো সংখ্যক ভাগ সমান করে করা যায়: /24 → চারটা /26 (প্রতিটায় 62 host) → আটটা /27 (৩০ করে)… প্রতি ধাপে এক bit borrow, ভাগ দ্বিগুণ, মাপ অর্ধেক।

VLSM — ভিন্ন মাপের ভাই

সমান ভাগ বাস্তবে বিরল — sales-এ 120 জন, engineering-এ 55, guest Wi-Fi- এ 18। Variable Length Subnet Mask (VLSM) নিয়ম: সবচেয়ে বড় চাহিদা আগে, সবচেয়ে ছোট block-গুলো পরে, প্রতিটা নতুন block আগেরটার শেষ-ঠিকানার পরে তার নিজের alignment-এ বসে। 192.168.50.0/24 থেকে:

Sales       120 hosts → /25 (126)   192.168.50.0/25      .0–.127
Engineering  55 hosts → /26 (62)    192.168.50.128/26    .128–.191
Guest        18 hosts → /27 (30)    192.168.50.192/27    .192–.223
সঞ্চয়                              192.168.50.224/27    .224–.255

খেয়াল করুন ক্রমটা কেন জরুরি: ছোট block আগে বসালে বড় block-এর alignment আর জায়গা নাও মিলতে পারে। বড়-আগে হলে বাকিটা স্বাভাবিকেই fit হয়। এই ধারাবাহিক packing-ই cloud-provider-দের VPC design-এর দৈনন্দিন কাজ।

Aggregation — টেবিল ছোট করার গণিত

Splitting-এর উল্টো দিক aggregation: পাশাপাশি, aligned কয়েকটা prefix মিলে একটা ছোট-prefix-এ। একটা ISP-র গ্রাহক-ব্লক ভাবুন — 203.0.112.0/24 থেকে 203.0.119.0/24, মোট আটটা /24:

আলাদা করে announce করলে:   ৮টা route-entry   (৮ × ২৫৬ = ২,০৪৮ ঠিকানা)
Aggregate করে /21 দিলে:     ১টা route-entry   (2^11 = ২,০৪৮ ঠিকানা)

একটা /21 = আটটা /24, ঠিকানা হিসেবে হুবহু সমান — কিন্তু global routing table-এ জায়গা নেয় ৮-এর বদলে ১ লাইন। আজকের internet- ব্যাপী table-এ প্রায় দশ লাখ route আছে CIDR-aggregation সহ; না থাকলে 1990-এর projection অনুযায়ী তা কোটি লাইন ছাড়িয়ে যেত — কোনো router তা ধরতেই পারত না। CIDR শুধু ঠিকানা বাঁচায়নি, ইন্টারনেটের নেভিগেশন-ব্যবস্থাই চালু রেখেছে।

উদাহরণ

একটা সম্পূর্ণ কাজ — শুরু থেকে শেষ

চলুন একটা realistic প্রশ্ন হাতে সমাধান করি: 172.16.37.99/21 — এর network, broadcast, host-range কী?

ধাপ ১ — সীমারেখা কোথায়: /21 = ২৪-এর আগে শেষ হয়, তাই সীমারেখা তৃতীয় octet-এর ভেতরে। প্রথম দুই octet (172.16) পুরোটাই network-part; শেষ octet (99) পুরোটাই host-part। লড়াই শুধু তৃতীয় octet-এ: 37।

ধাপ ২ — mask-এর তৃতীয় octet: /21 মানে তৃতীয় octet-এ ৫টা bit network (8+8+5=21): mask-octet 11111000 = 248।

ধাপ ৩ — 37-কে AND করা: 37 = 00100101; 00100101 AND 11111000 = 00100000 = 32। তাহলে network = 172.16.32.0/21।

ধাপ ৪ — block-এর মাপ: host-bits = 32−21 = 11 → block size 2^11 = 2048। তৃতীয় octet-এ এটা মানে ৮-এর ধাপে ৮টা মান (2048 = ৮×256): 32 থেকে 39।

ধাপ ৫ — সব উত্তর:

Network:    172.16.32.0
Broadcast:  172.16.39.255     (তৃতীয় octet 32+7=39, চতুর্থ 255)
First host: 172.16.32.1
Last host:  172.16.39.254
Usable:     2^11 − 2 = 2046

37-এর ভেতরের 00100-অংশ network-এ চলে গেছে, শেষ তিন bit (101) host-part — তাই 99-ও, 32-ও একই পাড়ার বাসিন্দা।

দ্বিতীয় কাজ — এক /24-এর পরিকল্পনা

একটা startup-এর দাবি: HQ-তে 100 host, branch-এ 45, lab-এ 12, আর router-to-router link-এ 2। বরাদ্দ: 203.0.113.0/24।

HQ      100 দরকার → /25 দেয় 126 ✓   203.0.113.0/25     .0–.127
Branch   45 দরকার → /26 দেয় 62  ✓   203.0.113.128/26   .128–.191
Lab      12 দরকার → /28 দেয় 14  ✓   203.0.113.192/28   .192–.207
P2P       2 দরকার → /30 দেয় 2   ✓   203.0.113.208/30   .208–.211
সঞ্চয়                                 .212–.255 (৪৪ ঠিকানা ভবিষ্যতের জন্য)

প্রতিটা ধাপে দুইটা সিদ্ধান্ত: (১) কোন prefix চাহিদা মেটায় — ছোটতম 2^(32−n) − 2 ≥ দরকার; (২) সেই মাপের alignment-এ আগের block-এর পরে বসা। Lab-এর 12-এর জন্য /27 (30) না নিয়ে /28 নেওয়াটাই VLSM- এর সার-কথা — ঠিকানা একটু একটু করে বাঁচানো, কারণ একদিন এই সঞ্চয়ই নতুন subnet-এর জন্ম দেয়।

ছবিতে

ঠিকানার অঙ্গসংস্থান

একটা IPv4 ঠিকানার ভেতরটা — prefix-এর দানা-বাঁধন
  1. Network part (/n পর্যন্ত)routing table-এ এই অংশই লেখা — পাড়া চেনার ঠিকানা
  2. Subnet part (borrow করা bits)host-part থেকে কেড়া bit — ভেতরের ভাগ চেনায়
  3. Host part (বাকি bits)subnet-এর ভেতরের বাড়ি-নম্বর; সব 0 = নামফলক, সব 1 = broadcast

Splitting-এর ছবি

              শেষ octet-এর bit:   b b b b b b b b
                                  ↑
                        borrowed bit (/25-এ)

Subnet A   0 0000000 … 0 1111111      192.168.1.0/25
           └── host-part ৭ bit ──┘    network .0   broadcast .127

Subnet B   1 0000000 … 1 1111111      192.168.1.128/25
                                      network .128 broadcast .255
/24 → দুই /25: borrowed bit-টা শেষ octet-এর MSB — তার মানই বলে দেয় ঠিকানাটা কোন অর্ধেকের বাসিন্দা।

Classful বনাম CIDR — এক নজরে

Classful:   0…                     → অনিবার্য /8   (১.৬ কোটি host!)
            10…                    → অনিবার্য /16
            110…                   → অনিবার্য /24

CIDR:       যেকোনো ঠিকানা + স্বাধীন /n
            203.0.113.0/24   ছোট office
            203.0.112.0/21   ISP-র আট-ব্লক bundle
            10.34.77.9/13    বড় enterprise-এর ভেতরের region
Classful যুগে সীমারেখা ঠিকানার প্রথম bit-এ লুকানো ছিল (A/B/C); CIDR-এ সেটা প্রতিটা route-এর সাথেই explicit — /n যেখানে দরকার সেখানেই বসে।

নিজে চালিয়ে দেখুন

EXPERIMENT

নিজের machine-এর ঠিকানা decode করুন, তারপর হাতে-হাতে drill

Linux / macOS· ২০ মিনিট

ধাপ ১ — নিজের ঠিকানা আনুন:

# Linux
ip -4 addr show
# macOS
ifconfig en0 | grep inet

যেমন একটা output: inet 192.168.1.20/24 ... brd 192.168.1.255। এখন কাগজে হিসাব করুন: network address, first/last host, usable count। তারপর kernel-এর উত্তরের সাথে মেলান:

# Linux — একই তথ্য route-ভাষায়
ip route show | grep 192.168.1
# macOS
netstat -rn | grep 192.168.1

192.168.1.0/24-এর link-route আর brd-value দেখবেন — আপনার হিসাবের হুবহু প্রতিধ্বনি।

ধাপ ২ — hand-drill set (উত্তরসহ):

প্রশ্ন ১: 168-এর binary? → 128+32+8 → 10101000

প্রশ্ন ২: 10.34.77.9/13 — network, broadcast, usable? → তৃতীয় octet mask 248; 77 AND 248 = 72 → network 10.32.0.0, broadcast 10.39.255.255, usable 2^19−2 = 524,286

প্রশ্ন ৩: /26-এ usable কত, আর এক /24 কয়টা /26 দেয়? → 62; ৪টা (.0, .64, .128, .192 — প্রতিটা 64-এর multiple)

প্রশ্ন ৪: 192.168.0.0/22-এ 192.168.2.255 কি বৈধ host? → হ্যাঁ। /22 বিস্তার .0.0–.3.255; broadcast .3.255; .2.255 সাধারণ host। (/24-মনস্কতার ফাঁদ!)

প্রশ্ন ৫: 203.0.112.0/24 + 203.0.113.0/24 এক /23-এ গুটানো যায়? → যায় — প্রথমটার তৃতীয় octet 112 (জোড়, 2-এর multiple)। কিন্তু 203.0.113.0 + 203.0.114.0? → যায় না — 113 বিজোড়, alignment ভাঙে; দুটোকে /23-এ লিখলে তা আসলে 112–115-এর /22-এর অর্ধেক নয়।

প্রশ্ন ৬: 100.64.13.5 কোন জাতের ঠিকানা? → CGNAT shared-space (100.64/10) — ব্যক্তিগত নয়, public-ও নয়।

ধাপ ৩ — python-এর ipaddress-কে referee বানান:

আপনার হাতের উত্তর cross-check করুন — মানসিক গণিতের সত্যতা যাচাইয়ে stdlib ব্যবহার করুন (নিজের হিসাবের বদলে নয়):

import ipaddress

drills = [
    ('192.168.1.20', 24),
    ('172.16.37.99', 21),
    ('10.34.77.9', 13),
    ('203.0.113.199', 25),
]
for ip_text, prefix in drills:
    net = ipaddress.ip_network(f'{ip_text}/{prefix}', strict=False)
    hosts = sum(1 for _ in net.hosts())
    print(f'{str(net):22} broadcast {str(net.broadcast_address):16} '
          f'usable {hosts}')

প্রতিটা লাইন আপনার ধাপ-২ হিসাবের সাথে মিললে আপনি production-grade subnetting fluency পেয়ে গেছেন। না মিললে — ভালো! ভুলটা এখনই ধরা পড়ল, মিটিং-রুমের whiteboard-এ না।

এটা কী প্রমাণ করে

kernel আপনার interface-এ যে network আর broadcast লেখে, সেটা আপনি কাগজে-কলমে AND-operation দিয়ে যা বের করবেন হুবহু তা-ই — subnetting-এর গণিত theory নয়, আপনার machine এই মুহূর্তে সেটাই চালাচ্ছে।

নিজে বানান

BUILD IT

subnetcalc — manual bit-math core, ipaddress শুধু বিচারক

Python · ●●○○○
  1. dotted-decimal ↔ 32-bit integer নিজের হাতে shift/OR দিয়ে লিখুন
  2. mask বানান শুধু shift আর AND-এ — library নিষেধ
  3. network = ip AND mask, broadcast = network OR inverted-mask
  4. first/last host আর usable count বের করে RFC1918/private শনাক্ত করুন
  5. --split অপশনে n-ভাগ সমান ভাঙা দেখান
  6. শেষে ipaddress module-কে oracle বানিয়ে নিজের ফল যাচাই করুন

লক্ষ্য: এই লেসনের সব সূত্র একটা CLI-তে জীবন্ত করা — কিন্তু core গণিতে ipaddress নিষিদ্ধ; সে শুধু শেষে বিচারকের চেয়ারে বসবে।

#!/usr/bin/env python3
import argparse

WEIGHTS = (128, 64, 32, 16, 8, 4, 2, 1)

def ip_to_int(text):
    parts = text.split('.')
    if len(parts) != 4:
        raise SystemExit(f'4টা octet লাগবে: {text}')
    value = 0
    for p in parts:
        n = int(p)
        if n > 255 or n < 0:
            raise SystemExit(f'octet সীমার বাইরে: {n}')
        value = (value << 8) | n          # আগেরটা ৮ ঘর উঁচুতে, নতুনটা নিচে
    return value

def int_to_ip(value):
    return '.'.join(str((value >> s) & 0xFF) for s in (24, 16, 8, 0))

def mask_of(prefix):
    if prefix < 0 or prefix > 32:
        raise SystemExit('prefix 0..32 হতে হবে')
    return (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF if prefix else 0

def analyze(ip_int, prefix):
    mask = mask_of(prefix)
    network = ip_int & mask                 # host-bits ধুয়ে ফেলা
    broadcast = network | (mask ^ 0xFFFFFFFF)  # host-bits সব 1
    hb = 32 - prefix
    usable = (1 << hb) - 2 if hb >= 2 else 0
    first = int_to_ip(network + 1) if hb >= 2 else '-'
    last = int_to_ip(broadcast - 1) if hb >= 2 else '-'
    o1, _, rest = int_to_ip(network).partition('.')
    o2, _, _ = rest.partition('.')
    private = (o1 == '10') or (o1 == '192' and rest.startswith('168')) or \
              (o1 == '172' and 16 <= int(o2) <= 31)
    return network, broadcast, first, last, usable, private

def report(ip_text, prefix):
    ip_int = ip_to_int(ip_text)
    network, broadcast, first, last, usable, private = analyze(ip_int, prefix)
    tag = ', RFC1918-private' if private else ''
    print(f'{ip_text}/{prefix}{tag}')
    print(f'  network    {int_to_ip(network)}')
    print(f'  first-last {first} … {last}')
    print(f'  broadcast  {int_to_ip(broadcast)}')
    print(f'  usable     {usable}')

def split(ip_text, prefix, parts):
    ip_int = ip_to_int(ip_text)
    network, *_ = analyze(ip_int, prefix)
    bits = parts.bit_length() - 1
    if 1 << bits != parts or prefix + bits > 32:
        raise SystemExit('parts হতে হবে 2-এর power, আর prefix বাড়ানো যায় কি না দেখুন')
    size = 1 << (32 - prefix - bits)
    for i in range(parts):
        report(int_to_ip(network + i * size), prefix + bits)

parser = argparse.ArgumentParser()
parser.add_argument('cidr')
parser.add_argument('--split', type=int, default=0)
args = parser.parse_args()
ip_text, _, pfx = args.cidr.partition('/')
if args.split:
    split(ip_text, int(pfx), args.split)
else:
    report(ip_text, int(pfx))

# ---- test oracle: stdlib ipaddress আমাদের হাতের গণিত যাচাই করে ----
import ipaddress
for t, p in [('192.168.1.20', 24), ('172.16.37.99', 21),
             ('10.34.77.9', 13), ('203.0.113.129', 25)]:
    ref = ipaddress.ip_network(f'{t}/{p}', strict=False)
    mine, *_rest = analyze(ip_to_int(t), p)
    assert mine == int(ref.network_address), f'MISMATCH {t}/{p}'
print('oracle: সব মিলেছে ✓')

চালান:

python3 subnetcalc.py 172.16.37.99/21
python3 subnetcalc.py 192.168.1.0/24 --split 4

প্রত্যাশিত output:

172.16.37.99/21
  network    172.16.32.0
  first-last 172.16.32.1 … 172.16.39.254
  broadcast  172.16.39.255
  usable     2046
192.168.1.0/24, RFC1918-private
  network    192.168.1.0
  first-last 192.168.1.1 … 192.168.1.126
  broadcast  192.168.1.127
  usable     126
192.168.1.128/25, RFC1918-private
  network    192.168.1.128
  first-last 192.168.1.129 … 192.168.1.254
  broadcast  192.168.1.255
  usable     126
oracle: সব মিলেছে ✓

নিজে বাড়ান:

  1. --vlsm 120,45,12,2 মোড যোগ করুন — example section-এর packing algorithm নিজেই লিখুন, alignment-violation ধরে error দিন
  2. Non-contiguous mask (যেমন 255.0.255.0) ইনপুটে এলে ব্যাখ্যাসহ প্রত্যাখ্যান করুন — কেন CIDR-এ অবৈধ
  3. --aggregate মোড: কয়েকটা prefix ইনপুট নিয়ে বলুন কি এক super-prefix-এ গুটানো সম্ভব, সম্ভব হলে সেটা দিন

বাস্তব সিস্টেমে

এই গণিত আজ কোথায় কোথায়

Cloud-এর VPC planning। AWS-এ VPC-র মাপ হতে হয় /16 থেকে /28-এর মধ্যে; প্রতিটা availability zone-এর subnet-ও একই সীমায়। Terraform template-এ cidrsubnet(vpc_cidr, 4, 2)-জাতীয় function-টা আসলে আজকের borrowing-গণিতের ব্যাখ্যাসহ wrapper — যিনি গণিতটা জানেন, তিনি template-টাও debug করতে পারেন।

Docker আর VM-দের default। Docker daemon নিজে থেকেই docker0 bridge-এ 172.17.0.0/16 বসায়; আপনার company network যদি ভেতরে 172.16/12 ব্যবহার করে, সেই conflict-টাই “container-এ ping চলে না”-জাতীয় ticket-এর আসল কারণ — ঠিকানার গণিত না জানলে এই bug-এর গন্ধই পাবেন না।

ISP allocation আর DFZ। প্রতিটা ISP RIPE/ARIN-এর মতো registry থেকে বড় block (যেমন /22) নিয়ে গ্রাহকদের ছোট ছোট ভাগে দেয়, তারপর aggregate করে একটা announcement-এ বিক্রি করে — routing লেসনে দেখব এই announcement-ই BGP-র কাঁচামাল। Global table আজ প্রায় ১০ লাখ route — aggregation ছাড়া সংখ্যাটা অগণনযোগ্য।

Home router-এর factory setting। প্রায় সব বাড়ির router 192.168.1.1/24 নিয়ে জন্মায় — এবং ঠিক এই কারণেই আপনার অফিস VPN-ও 192.168.1.x হলে দুই পাড়ার ঠিকানা ধাক্কা খায়। পেশাদার setup-এ বাড়িকে অন্য RFC1918-corner (যেমন 192.168.73.0/24)-এ সরিয়ে নেওয়াই conflict- proofing।

CGNAT-যুগের shared ঠিকানা। Mobile operator-রা লাখো subscriber- কে 100.64/10-space-এ বসিয়ে তারপর এক handful public IP-তে NAT করে — nat লেসনে এর খরচ-সুবিধা দুই দিকই দেখবেন।

যে ভুলগুলো সবাই করে

“Netmask-এর 1-গুলো যেকোনো জায়গায় বসতে পারে — 255.0.255.0-ও একটা বৈধ mask।”

CIDR-এ mask-এর 1-গুলো অবিচ্ছিন্নভাবে বাঁ দিকেই থাকতে হয় — নইলে “prefix” বলার মতো কোনো সংখ্যাই থাকে না। 255.0.255.0-এর মতো non-contiguous mask পুরনো কিছু software-এ টাইপ করা যেত, কিন্তু তা কোনো বাস্তব routing-গণিতে খাপ খায় না: network/host ভাগ দুই টুকরো হয়ে যায়। আজকের সব OS আর router এমন ইনপুট প্রত্যাখ্যান করে।

“/24 subnet-এ ২৫৬টা host রাখা যায়।”

২৫৬টা হলো মোট ঠিকানা-pattern; তার মধ্যে all-zeros হলো network-এর নামফলক, all-ones হলো broadcast — ব্যবহারযোগ্য ২৫৪। ছোট মাপে এই overhead-এর আনুপাতিক দাম বাড়ে: /29 দেয় ৮-এর বদলে ৬, অর্থাৎ 25% কাটছাঁট। Capacity-planning-এ সবসময় 2^(32−n)−2-ই লিখুন।

“Private ঠিকানা internet-এ কোনোভাবেই যেতে পারে না — এটা প্রযুক্তিগত অসম্ভবতা।”

RFC1918 ঠিকানা-বহনকারী packet-এর কোনো magic-flag নেই — packet হিসেবে তা internet-এ ভেসে যেতে পারেই। তা যায় না কারণ তিনটা সম্মতি: registry-রা এগুলো allocate করে না, ISP-রা ingress-filter করে, আর border router-রা এগুলো NAT করে। নিয়ম ভাঙার দরকার পড়লে (যেমন misconfigured VPN-এ) ভাঙাটা প্রযুক্তিগতভাবে সহজ — এবং বিপজ্জনক।

“Loopback মানে শুধু 127.0.0.1 — অন্য 127.x লিখলে error।”

পুরো 127.0.0.0/8-ই loopback — ping 127.8.8.8 একই machine-এ ফিরে আসবে। এই জায়গাটা ইচ্ছেমতো বিশাল রাখা: local development-এ একই port-এ ভিন্ন ভিন্ন fake-host চালাতে এটা কাজে লাগে। শুধু মনে রাখুন browser-রা *.localhost ছাড়া 127-x-name resolve নাও করতে পারে।

বুঝেছেন কি না দেখুন

1

Netmask আর prefix-notation একই তথ্য কীভাবে বহন করে? /20-এর decimal mask কী?

স্মরণ

Prefix বলে কয়টা leading bit network-part — সেই সংখ্যক 1 বাঁ দিকে বসিয়ে 32-bit বানালেই decimal mask। /20 → ৮+৮+৪: তৃতীয় octet-এ 11110000 = 240 → 255.255.240.0।

2

172.16.37.99/21-এর network, broadcast আর usable host count বের করুন — প্রতিটা ধাপ লিখে।

প্রয়োগ

তৃতীয় octet-এ সীমা: mask-octet 248; 37=00100101 AND 248 = 00100000=32 → network 172.16.32.0; host-bits 11 → block 2048 = ৮ octet-মান → broadcast 172.16.39.255; usable 2^11−2 = 2046।

3

10.0.0.0/24-কে সমান চার ভাগে ভাঙুন — প্রতিটার range লিখুন। এক ভাগে usable কত?

প্রয়োগ

দুই bit borrow → চারটা /26: 10.0.0.0/26 (.1–.62), 10.0.0.64/26 (.65–.126), 10.0.0.128/26 (.129–.190), 10.0.0.192/26 (.193–.254)। প্রতিটায় 2^6−2 = 62 host।

4

203.0.113.0/24 আর 203.0.114.0/24 এক /23-এ মেলানো যায় না কেন, অথচ 203.0.112.0/24-এর সাথে মেলে? নিয়মটা সাধারণ ভাষায় বলুন।

যুক্তি

/23-এর প্রতিটা block তার মাপের (512-এর) multiple-এ শুরু হয় — তৃতীয় octet-এ মানে জোড় সংখ্যা। 112 জোড় → 112+113 এক /23-এর দুই অর্ধেক; 113 বিজোড় → তার /23-সঙ্গী 112 হতে পারে 114 নয়। সাধারণ নিয়ম: ভাঙা-গুটানো সবসময় alignment-মানে “শুরু ঠিকানা block-মাপের multiple” — মেনে চলে।

5

Route aggregation কীভাবে global routing table-কে বাঁচায় — একটা সংখ্যাসহ উদাহরণ দিন। কখন aggregation করা যায় না?

যুক্তি

ISP-র আটটা পাশাপাশি /24 (203.0.112.0–203.0.119.0) এক /21 হলে table-এ ৮-এর জায়গায় ১ লাইন, ঠিকানা-coverage হুবহু এক — এই অনুপাতেই দশ-লাখ-route table টিকে আছে। Aggregation ভাঙে যখন block-গুলো contiguous বা aligned নয়, আর ব্যবহারিকভাবে যখন একটা ভাগ অন্য ISP-র কাছে চলে যায় (deaggregation তখন অনিবার্য)।

6

192.168.50.0/24 থেকে তিন department-এর জন্য 120, 60 আর 20 host- এর subnet plan করুন। ক্রম কেন সেইটাই, ব্যাখ্যাসহ।

ডিজাইন

বড়-আগে: 192.168.50.0/25 (126 ≥ 120), তারপর 192.168.50.128/26 (62 ≥ 60), তারপর 192.168.50.192/27 (30 ≥ 20); বাকি .224–.255 ভবিষ্যতের সঞ্চয়। উল্টো ক্রমে ছোট block আগে বসালে বড় block-এর 128-alignment আর খালি জায়গা একসাথে মেলত না — তাই VLSM-এ descending-order packing নিয়ম।

এরপর কী

এরপর কী

আজ দেখলাম ৩২-bit ঠিকানার পুরো গণিত — আর সেই গণিতের একটা অন্ধকার কোণও: মানুষ যত বাড়ছে, 2^32 ≈ ৪৩ কোটি ঠিকানা তত ছোট হয়ে আসছে। CIDR অপচয় কমিয়েছে, NAT সাময়িকভাবে দিন গড়িয়েছে — কিন্তু সমাধান নয়, বরং জীবন-দীর্ঘায়ু।

পরের লেসনে:

  • IPv6: 128-bit ঠিকানা — প্রতি বর্গমিটার পৃথিবীর ভূপৃষ্ঠে হাজার কোটি ঠিকানার হিসাব
  • নতুন header-এর দর্শন: কী ফেলে দেওয়া হলো (checksum, router- fragmentation) আর কেন নিরাপদ
  • :: compression-এর নিয়ম, SLAAC, privacy extensions
  • Transition-এর বাস্তবতা: dual-stack, tunneling, NAT64

আজকের 2^(32−n)−2-এর সংকীর্ণতাই পরের লেসনের 340 অন্ডেসিলিয়ন- ঠিকানার মোটিভেশন। দেখা হবে 128-bit-এ।

আরও পড়ুন

  • RFC 1918 — Address Allocation for Private Internets — Y. Rekhter, B. Moskowitz, D. Karrenberg et al., IETF · Private-range-এর মূল spec — NAT-যুগের ভূমিকা-পত্র
  • RFC 4632 — Classless Inter-Domain Routing (CIDR) — V. Fuller, T. Li, IETF · Classful থেকে classless transition-এর official history ও rationale
  • Computer Networking: A Top-Down Approach — Network Layer, addressing অধ্যায় — Kurose & Ross · Subnetting আর CIDR-এর পাঠ্যপুস্তক-ধাঁচের ব্যাখ্যা