Data Link Layer Framing Methods
def char_stuffing(data, flag='F', esc='E'):
stuffed = data.replace(esc, esc+esc).replace(flag, esc+flag)
return flag + stuffed + flag
# Bit Stuffing
def bit_stuffing(data):
stuffed = data.replace('11111', '111110')
return stuffed + '111111'
data = "101111011111101"
print("Char Stuffed:", char_stuffing(data))
print("Bit Stuffed:", bit_stuffing(data))
Char Stuffed: F101111011111101F
Bit Stuffed: 1011110111110101111111
Go Back - N
def sliding_window(data, window_size):
for i in range(0, len(data), window_size):
window = data[i:i+window_size]
print("Sending:", window)
ack = input("Ack received for {}? (y/n): ".format(window))
if ack.lower() != 'y':
print("Resending:", window)
sliding_window("ABCDEFG", 3)
Sending: ABC
Resending: ABC
Sending: DEF
Resending: DEF
Sending: G
Resending: G
Broadcast Tree
import networkx as nx
def broadcast_tree(edges):
graph = nx.Graph()
# Add edges with weights
graph.add_weighted_edges_from(edges)
# Compute the minimum spanning tree
tree = nx.minimum_spanning_tree(graph)
return tree.edges
edges = [('A', 'B', 1), ('B', 'C', 2), ('C', 'D', 1), ('A', 'D', 4)]
print("Broadcast Tree:", broadcast_tree(edges))
Broadcast Tree: [('A', 'B'), ('B', 'C'), ('C', 'D')]
Dijkstra's Algorithm
import networkx as nx
def all_shortest_paths(graph):
return dict(nx.all_pairs_dijkstra_path_length(graph))
# Create a graph with nodes and weighted edges
graph = nx.DiGraph()
graph.add_weighted_edges_from([
('A', 'B', 1),
('B','C',2),
('C','D',3),
('D','A',4)
])
# Find shortest paths for every node
shortest_paths = all_shortest_paths(graph)
for source, paths in shortest_paths.items():
print(f"From {source}: {paths}")
From A: {'A': 0, 'B': 1, 'C': 3, 'D': 6}
From B: {'B': 0, 'C': 2, 'D': 5, 'A': 9}
From C: {'C': 0, 'D': 3, 'A': 7, 'B': 8}
From D: {'D': 0, 'A': 4, 'B': 5, 'C': 7}
Data Encryption and Decryption
from cryptography.fernet import Fernet
# Generate key
key = Fernet.generate_key()
cipher = Fernet(key)
def encrypt(data):
return cipher.encrypt(data.encode())
def decrypt(enc_data):
return cipher.decrypt(enc_data).decode()
data = "HelloWorld"
encrypted = encrypt(data)
print("Encrypted:", encrypted)
print("Decrypted:", decrypt(encrypted))
Encrypted: b'gAAAAABndnxbSeJ_JapyMOwXbtizoVKRAVutqxVYNmhfvw2K-ONqSgagAdLw_K8g_N3-
DD54kxPEiFI0EtoA9EhghiMZpDAYZA=='
Decrypted: HelloWorld
Distance Vector Routing
def distance_vector(graph):
dist = {}
# Initialize distances
for u in graph:
dist[u] = {}
for v in graph:
dist[u][v] = float('inf')
dist[u][u] = 0 # Distance to itself is 0
# Set initial distances to neighbors
for u in graph:
for v, weight in graph[u]:
dist[u][v] = weight
# Update distances using Distance Vector Algorithm
for _ in graph:
for u in graph:
for v in graph:
for w in graph:
dist[u][w] = min(dist[u][w], dist[u][v] + dist[v][w])
return dist
# Example graph
graph = {
'A': [('B', 1), ('D', 4)],
'B': [('A', 1), ('C', 2)],
'C': [('B', 2), ('D', 3)],
'D': [('C',3),('A',4)]
}
# Calculate and print routing tables
distances = distance_vector(graph)
for key,value in distances.items():
print(f"From {key} : {value}")
From A : {'A': 0, 'B': 1, 'C': 3, 'D': 4}
From B : {'A': 1, 'B': 0, 'C': 2, 'D': 5}
From C : {'A': 3, 'B': 2, 'C': 0, 'D': 3}
From D : {'A': 4, 'B': 5, 'C': 3, 'D': 0}
CRC( for any type of Generator)
def compute_crc(data, generator):
data = list(data + '0' * (len(generator) - 1)) # Append zeros to the data
generator = list(generator)
for i in range(len(data) - len(generator) + 1): # Loop through the data
if data[i] == '1': # Perform XOR only if the current bit is 1
for j in range(len(generator)):
if data[i + j] == generator[j]: # Compare bits
data[i + j] = '0' # Replace with 0 if bits are the same
else:
data[i + j] = '1' # Replace with 1 if bits are different
# Calculate the remainder
remainder_length = len(generator) - 1 # How many bits to extract
remainder = ''.join(data[-remainder_length:]) # Extract last bits
return remainder # Return the CRC remainder
# Example usage
data = "1101011011" # Input data
print("CRC-12:", compute_crc(data, "1100000001111"))
print("CRC-16:", compute_crc(data, "11000000000000101"))
print("CRC-CCIP:", compute_crc(data, "10101000000100001"))
CRC-12: 110001100100
CRC-16: 1000101111011001
CRC-CCIP: 1000001111100011