🔷 6.1 MAC Addresses & VLANs
Overview
MAC (Media Access Control) addresses operate at Layer 2 for local network communication, while VLANs (Virtual LANs) logically segment networks. Both are fundamental to network design and operation.
1. MAC Addresses (Media Access Control)
🔷 Layer 2 Physical Addressing
Purpose: MAC addresses uniquely identify network interface cards (NICs) on a local network segment
MAC Address Structure
# MAC Address Format: XX:XX:XX:XX:XX:XX (48 bits = 6 bytes)
Example: 00:1A:2B:3C:4D:5E
BREAKDOWN:
00:1A:2B Organizationally Unique Identifier (OUI)
- First 24 bits
- Assigned by IEEE to manufacturer
- 00:1A:2B = Cisco Systems
3C:4D:5E Device Identifier
- Last 24 bits
- Assigned by manufacturer
- Unique to each network card
Common Formats:
• Colon notation: 00:1A:2B:3C:4D:5E
• Hyphen notation: 00-1A-2B-3C-4D-5E
• Dot notation: 001A.2B3C.4D5E (Cisco)MAC Address Types
| Type | Format | Purpose |
|---|---|---|
| Unicast | LSB of first octet = 0 | Single destination device |
| Multicast | LSB of first octet = 1 | Group of devices |
| Broadcast | FF:FF:FF:FF:FF:FF | All devices on LAN |
MAC Address Usage
- ARP (Address Resolution Protocol): Maps IP to MAC addresses
- Switching: Switches learn MAC addresses to forward frames
- MAC Address Table: Switches maintain CAM table mapping MAC to ports
- Security: Port security limits MAC addresses per switch port
- DHCP: Uses MAC address to identify clients
# Python - Working with MAC Addresses
import re
def validate_mac(mac):
"""Validate MAC address format"""
pattern = r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'
return bool(re.match(pattern, mac))
def normalize_mac(mac):
"""Convert to standard format"""
# Remove separators and convert to uppercase
mac_clean = mac.replace(':', '').replace('-', '').replace('.', '')
# Insert colons every 2 characters
return ':'.join(mac_clean[i:i+2] for i in range(0, 12, 2))
# Example
mac1 = "00:1a:2b:3c:4d:5e"
mac2 = "00-1A-2B-3C-4D-5E"
mac3 = "001A.2B3C.4D5E"
print(validate_mac(mac1)) # True
print(normalize_mac(mac2)) # 00:1A:2B:3C:4D:5E
print(normalize_mac(mac3)) # 00:1A:2B:3C:4D:5E2. VLANs (Virtual LANs)
🔀 Logical Network Segmentation
Purpose: VLANs create separate broadcast domains on a single physical switch, improving security and network performance
VLAN Benefits
- Broadcast Domain Separation: Limits broadcast traffic to VLAN members only
- Security Isolation: Separate sensitive traffic (e.g., finance VLAN from guest VLAN)
- Flexibility: Group users logically regardless of physical location
- Performance: Reduce unnecessary broadcast traffic
- Simplified Management: Easier to manage user groups
VLAN Types
| VLAN Type | ID Range | Purpose |
|---|---|---|
| Default VLAN | VLAN 1 | Factory default, all ports initially in VLAN 1 |
| Data VLANs | 2-1001 | User traffic, regular network data |
| Voice VLAN | Configured | Dedicated to VoIP traffic (QoS priority) |
| Native VLAN | Usually 1 | Untagged traffic on trunk ports |
| Management VLAN | Configured | Switch management traffic (SSH, SNMP) |
| Extended VLANs | 1006-4094 | Enterprise networks (requires VTP transparent) |
VLAN Configuration Example
# Cisco IOS Switch Configuration ! Create VLANs Switch(config)# vlan 10 Switch(config-vlan)# name Engineering Switch(config-vlan)# exit Switch(config)# vlan 20 Switch(config-vlan)# name Sales Switch(config-vlan)# exit Switch(config)# vlan 30 Switch(config-vlan)# name Guest Switch(config-vlan)# exit ! Assign ports to VLANs (Access Ports) Switch(config)# interface range fa0/1-10 Switch(config-if-range)# switchport mode access Switch(config-if-range)# switchport access vlan 10 Switch(config-if-range)# exit ! Configure trunk port (carries multiple VLANs) Switch(config)# interface gi0/1 Switch(config-if)# switchport trunk encapsulation dot1q Switch(config-if)# switchport mode trunk Switch(config-if)# switchport trunk allowed vlan 10,20,30 Switch(config-if)# switchport trunk native vlan 99
Engineering"] A --> C["VLAN 20
Sales"] A --> D["VLAN 30
Guest"] B --> B1["PC1"] B --> B2["PC2"] C --> C1["PC3"] C --> C2["PC4"] D --> D1["Laptop1"] style A fill:#667eea,stroke:#764ba2,stroke-width:3px,color:#fff style B fill:#66bb6a,stroke:#2e7d32,stroke-width:2px,color:#fff style C fill:#42a5f5,stroke:#1976d2,stroke-width:2px,color:#fff style D fill:#ffa726,stroke:#e65100,stroke-width:2px,color:#fff
3. VLAN Trunking & Inter-VLAN Routing
🔗 Connecting VLANs Across Switches
Concept: Trunk ports carry traffic for multiple VLANs, and routing enables communication between VLANs
Access Ports vs Trunk Ports
| Port Type | VLANs | Tagging | Use Case |
|---|---|---|---|
| Access Port | Single VLAN | Untagged | End devices (PCs, printers) |
| Trunk Port | Multiple VLANs | 802.1Q tagged | Switch-to-switch, switch-to-router |
802.1Q VLAN Tagging
# 802.1Q Frame Structure
[Dest MAC][Src MAC][802.1Q Tag][Type][Data][FCS]
802.1Q Tag (4 bytes):
- TPID (Tag Protocol ID): 0x8100 (2 bytes)
- PCP (Priority): 3 bits (QoS priority 0-7)
- DEI (Drop Eligible): 1 bit
- VID (VLAN ID): 12 bits (VLAN 0-4095)
Example:
Untagged Frame (Access Port):
→ [Dest][Src][Type][Data][FCS]
Tagged Frame (Trunk Port):
→ [Dest][Src][0x8100][VID=10][Type][Data][FCS]Inter-VLAN Routing
For devices in different VLANs to communicate, you need a Layer 3 device (router or Layer 3 switch):
# Router-on-a-Stick Configuration Router(config)# interface gi0/0.10 Router(config-subif)# encapsulation dot1Q 10 Router(config-subif)# ip address 192.168.10.1 255.255.255.0 Router(config-subif)# exit Router(config)# interface gi0/0.20 Router(config-subif)# encapsulation dot1Q 20 Router(config-subif)# ip address 192.168.20.1 255.255.255.0 Router(config-subif)# exit Router(config)# interface gi0/0 Router(config-if)# no shutdown # Layer 3 Switch (SVI - Switched Virtual Interface) Switch(config)# ip routing Switch(config)# interface vlan 10 Switch(config-if)# ip address 192.168.10.1 255.255.255.0 Switch(config-if)# no shutdown Switch(config-if)# exit Switch(config)# interface vlan 20 Switch(config-if)# ip address 192.168.20.1 255.255.255.0 Switch(config-if)# no shutdown
192.168.10.0/24"] --> R["Router/L3 Switch"] B["VLAN 20
192.168.20.0/24"] --> R C["VLAN 30
192.168.30.0/24"] --> R R --> D["Routes between VLANs"] style R fill:#667eea,stroke:#764ba2,stroke-width:3px,color:#fff style A fill:#66bb6a,stroke:#2e7d32,stroke-width:2px,color:#fff style B fill:#42a5f5,stroke:#1976d2,stroke-width:2px,color:#fff style C fill:#ffa726,stroke:#e65100,stroke-width:2px,color:#fff
4. Python Script - MAC and VLAN Operations
🐍 Automating Layer 2 Operations
Example: Using Python to query and configure VLANs
# Python - Query VLANs via RESTCONF
import requests
from requests.auth import HTTPBasicAuth
device_ip = "192.168.1.1"
url = f"https://{device_ip}/restconf/data/Cisco-IOS-XE-native:native/vlan"
headers = {
"Accept": "application/yang-data+json",
"Content-Type": "application/yang-data+json"
}
response = requests.get(
url,
auth=HTTPBasicAuth('admin', 'cisco'),
headers=headers,
verify=False
)
vlans = response.json()
for vlan in vlans['Cisco-IOS-XE-native:vlan']['vlan-list']:
print(f"VLAN {vlan['id']}: {vlan.get('name', 'Unnamed')}")
# Create new VLAN
new_vlan = {
"Cisco-IOS-XE-native:vlan-list": {
"id": 50,
"name": "IoT_Devices"
}
}
response = requests.post(
url,
json=new_vlan,
auth=HTTPBasicAuth('admin', 'cisco'),
headers=headers,
verify=False
)
print(f"VLAN created: {response.status_code}")🌍 6.2 IP Addresses, Routes, Subnet Masks & Gateways
Overview
IP addressing operates at Layer 3, enabling communication across different networks. Understanding IP addresses, subnet masks, routing, and gateways is fundamental to network connectivity and automation.
1. IP Addresses (IPv4)
📍 32-bit Network Layer Addressing
Purpose: IP addresses uniquely identify devices on a network and enable routing across internetworks
| Principle | Description |
|---|---|
| Be Constructive | Focus on improving code, not criticizing the person |
| Be Specific | Point to exact lines, provide examples and suggestions |
| Be Thorough | Check functionality, security, performance, and style |
| Be Timely | Review promptly to avoid blocking team members |
| Ask Questions | Understand intent before suggesting changes |
| Praise Good Code | Acknowledge clever solutions and improvements |
| Test the Code | Pull branch locally and verify it works |
| Follow Standards | Ensure code follows team conventions |
2. Subnet Masks and CIDR Notation
🔢 Network and Host Portion Separation
Purpose: Subnet masks define which part of an IP address identifies the network and which part identifies the host
| Benefit | Description | Impact |
|---|---|---|
| Bug Detection | Catch errors before production | Reduced bugs, fewer hotfixes |
| Knowledge Sharing | Team learns from each other's code | Improved team skills, cross-training |
| Code Quality | Maintain high standards | Better maintainability, readability |
| Security | Identify vulnerabilities early | Reduced security risks |
| Consistency | Enforce coding standards | Uniform codebase |
| Mentoring | Senior developers guide juniors | Faster team growth |
| Documentation | Ensure code is well-commented | Easier onboarding, maintenance |
| Collaboration | Team ownership of code | Reduced silos, shared responsibility |
3. Code Review Checklist
🔍 What to Look For
Comprehensive Review Areas: Key aspects to evaluate during review
- Functionality: Does the code do what it's supposed to?
- Logic: Are there any logical errors or edge cases missed?
- Security: SQL injection, XSS, authentication issues?
- Performance: Inefficient loops, unnecessary API calls?
- Error Handling: try/except blocks, proper validation?
- Testing: Unit tests included? Test coverage sufficient?
- Readability: Clear variable names, proper comments?
- Standards: Follows team coding conventions?
- Dependencies: New libraries justified and secure?
- Documentation: Docstrings, README updates?
- Scalability: Will it handle growth?
- Complexity: Is it overly complex? Can it be simplified?
4. Code Review Best Practices
💡 Effective Review Practices
For Reviewers:
- ✅ Review small pull requests (< 400 lines)
- ✅ Leave constructive, actionable comments
- ✅ Suggest improvements with code examples
- ✅ Ask questions to understand design decisions
- ✅ Approve when requirements are met
- ✅ Request changes with clear explanations
- ✅ Use a respectful, collaborative tone
For Authors:
- ✅ Keep pull requests small and focused
- ✅ Write clear PR descriptions
- ✅ Self-review before requesting review
- ✅ Include tests with code changes
- ✅ Respond promptly to feedback
- ✅ Be open to suggestions
- ✅ Update documentation when needed
# Example Pull Request Description ## What does this PR do? Adds error handling and retry logic to Meraki API client ## Why is this change needed? Current implementation fails when API rate limits are hit. This adds exponential backoff retry mechanism. ## How was this tested? - Unit tests added (test_api_retry.py) - Tested against Meraki sandbox with rate limiting - All existing tests pass ## Checklist - [x] Tests included - [x] Documentation updated - [x] No security issues - [x] Follows coding standards ## Related Issues Fixes #123
5. Code Review Tools
🔧 Platform Features
| Platform | Key Features |
|---|---|
| GitHub | Pull Requests, inline comments, status checks, branch protection |
| GitLab | Merge Requests, approval rules, code quality reports |
| Bitbucket | Pull Requests, required reviewers, merge checks |
| Gerrit | Change-based reviews, voting system, automated testing |
Automated Tools
- Linters: pylint, eslint, flake8 (code style)
- Security Scanners: Snyk, SonarQube, Bandit
- Test Coverage: pytest-cov, coverage.py
- Static Analysis: mypy, pytype (type checking)
🔧 6.3 Common Networking Components
Overview
Network components like switches, routers, firewalls, and load balancers each serve specific functions in network infrastructure. Understanding their roles is essential for network design and automation.
1. Switches
🔀 Layer 2 Frame Forwarding
Function: Switches forward frames based on MAC addresses within a local network segment
This sequence diagram shows a two-phase process:
- Phase 1 (Lines 1-6): User logs in with username/password, receives a JWT token
- Phase 2 (Lines 7-12): User makes API requests using the token instead of password
Step-by-Step Interpretation
PHASE 1: LOGIN AND GET TOKEN Step 1: User enters username and password into Client App Step 2: Client sends POST request to /api/v1/auth/login with credentials Step 3: Auth API queries Database to verify username and password Step 4: Database confirms user is valid Step 5: Auth API returns 200 OK with JWT token (e.g., "abc123...") Step 6: Client App stores the token locally (memory, localStorage, etc.) PHASE 2: USE TOKEN FOR API CALLS Step 7: User requests to see device list Step 8: Client sends GET /api/v1/devices with "Authorization: Bearer abc123" header Step 9: Device API validates the token is authentic and not expired Step 10: Device API queries Database for device records Step 11: Database returns list of devices Step 12: Device API returns 200 OK with JSON array of devices Step 13: Client App displays devices to User KEY INSIGHTS: ✅ Password is only sent ONCE during login (Step 2) ✅ Token is used for ALL subsequent API calls (Step 8, etc.) ✅ Token can expire and requires re-authentication ✅ More secure than sending password with every request
2. Routers
🌐 Layer 3 Packet Routing
Function: Routers forward packets between different networks based on IP addresses and routing tables
This shows cloud-managed networking where API calls flow through the Meraki Dashboard to cloud controllers, which then push configs to physical devices.
Step-by-Step Interpretation
Step 1-2: Script retrieves organization list using API key authentication → Response: Organization ID 123 named "Corp" Step 3-6: Script creates new wireless network in organization 123 → POST request with network name and type → Meraki provisions network in cloud → Response: Network ID "net-456" created (HTTP 201) Step 7-12: Script configures WiFi SSID on the new network → PUT request to update SSID 0 → Cloud controller receives config update → Config is pushed to physical Access Point → AP applies the configuration → Success confirmation flows back through cloud to API → Response: 200 OK WORKFLOW PATTERN: 1. GET (retrieve org ID) 2. POST (create new resource) 3. PUT/PATCH (configure resource) KEY INSIGHT: • Cloud-managed: Changes go through API → Cloud → Device • No direct device access needed • Centralized management
3. Firewalls
🛡️ Network Security and Traffic Filtering
Function: Firewalls control incoming and outgoing network traffic based on security rules and policies
Shows how DNA Center discovers devices, assigns them to sites, and deploys configuration templates.
Step-by-Step Interpretation
AUTHENTICATION:
Step 1-4: Script authenticates to DNA Center
→ POST to /auth/token with credentials
→ DNAC validates user in database
→ Returns authentication token (xyz789)
DEVICE DISCOVERY:
Step 5-9: Script initiates device discovery
→ POST device IP address (10.1.1.1)
→ DNAC uses CDP/LLDP to discover device
→ Router responds with device information
→ DNAC stores device in inventory database
→ Returns task ID (202 Accepted - async operation)
TASK MONITORING:
Step 10-11: Script polls for task completion
→ GET /task/{taskId} to check status
→ Returns progress update
TEMPLATE DEPLOYMENT:
Step 12-15: Script deploys configuration template
→ POST with device ID and template ID
→ DNAC pushes config to router via NETCONF
→ Router applies configuration
→ Returns 200 OK (success)
PATTERN:
• Asynchronous operations (discovery returns task ID)
• Polling required for long-running tasks
• Uses NETCONF for device configuration4. Load Balancers
⚖️ Traffic Distribution and High Availability
Function: Load balancers distribute incoming traffic across multiple servers to optimize resource usage and ensure availability
Demonstrates error handling in API calls - what happens when configuration fails and how to handle rollback scenarios.
Step-by-Step Interpretation
SUCCESSFUL CONFIGURATION (Steps 1-8): Step 1-4: Script reads current interface configuration → GET interface Gi1 current state → Device OS retrieves config → Returns interface is disabled (enabled: false) Step 5-8: Script updates interface configuration → PATCH to enable interface and add description → Device OS applies the changes → Returns 204 No Content (successful, no body needed) ERROR SCENARIO (Steps 9-13): Step 9-12: Script attempts to configure non-existent interface → PATCH interface Gi99 (which doesn't exist) → Device OS checks interface existence → Interface not found in configuration → Returns 404 Not Found with error message Step 13: Script handles error gracefully → Logs the error for troubleshooting → Continues with next operation (doesn't crash) KEY INSIGHTS: ✅ Always GET before PATCH to verify resource exists ✅ Handle HTTP error codes (404, 400, 500) ✅ Implement try/except in scripts ✅ Log errors for debugging
5. Reading Sequence Diagrams - Quick Reference
📚 Sequence Diagram Symbols and Notation
Reference Guide: Understanding all sequence diagram elements
| Symbol/Notation | Meaning | Example |
|---|---|---|
| participant | Actor/system in diagram | participant S as Script |
| ->> | Synchronous call (solid line) | A->>B: Request |
| -->> | Response (dashed line) | B-->>A: Response |
| ->>+ | Call activates participant | A->>+B: Start |
| -->>- | Response deactivates | B-->>-A: End |
| Note over A,B | Add notes/comments | Note over: Phase 1 |
| alt/else/end | Conditional logic | alt success / else fail |
| loop/end | Repeated operations | loop Every 5 seconds |
Common API Patterns in Sequence Diagrams
| Pattern | Description | APIs |
|---|---|---|
| Authentication | Login → Get token → Use token | DNA Center, ACI, Custom APIs |
| CRUD Operations | GET → POST → PUT → DELETE | REST APIs, RESTCONF |
| Async Processing | POST → Get task ID → Poll status | DNA Center, NSO |
| Error Handling | Request → Error response → Retry/Log | All APIs |
| Multi-tier | Client → API → Controller → Device | Meraki, DNA Center |
🐍 Interactive Python Interpreter
- Write Python code in the editor
- Click "▶ Run Code" to execute
- Try sample code buttons