Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 29 additions & 14 deletions scripts/fast-reboot-dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,46 @@
import argparse
import syslog
import traceback
import ipaddress


ARP_CHUNK = binascii.unhexlify('08060001080006040001') # defines a part of the packet for ARP Request
ARP_PAD = binascii.unhexlify('00' * 18)

def generate_arp_entries(filename, all_available_macs):
def generate_neighbor_entries(filename, all_available_macs):
db = swsssdk.SonicV2Connector(host='127.0.0.1')
db.connect(db.APPL_DB, False) # Make one attempt only

arp_output = []
arp_entries = []
neighbor_entries = []
keys = db.keys(db.APPL_DB, 'NEIGH_TABLE:*')
keys = [] if keys is None else keys
for key in keys:
vlan_name = key.split(':')[1]
ip_addr = key.split(':')[2]
entry = db.get_all(db.APPL_DB, key)
if (vlan_name, entry['neigh'].lower()) not in all_available_macs:
mac = entry['neigh'].lower()
if (vlan_name, mac) not in all_available_macs:
# FIXME: print me to log
continue
obj = {
key: entry,
'OP': 'SET'
}
arp_entries.append((vlan_name, entry['neigh'].lower(), ip_addr))
arp_output.append(obj)

ip_addr = key.split(':')[2]
if ipaddress.ip_interface(ip_addr).ip.version != 4:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This is a necessary modification in 201911 to handle IPv6 entries.
But there is some problem using the ipaddress.ip_interface(ip_addr).ip.version to parse it.
From my opinion, I will consider using some simple checking like
if '.' not in ip_addr:
If no '.' inside the ip_addr, it is a IPv6 address.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we identified there is problem with script, why is it taken to 201911? @qiluo-msft, @tahmed-dev, @abdosi . This is breaking the 201911 fastboot.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@prsunny Do you have a Github issue? Are you suggesting revert?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will suggest replace the line if ipaddress.ip_interface(ip_addr).ip.version != 4: with this line if '.' not in ip_addr: to handle the IPv6 entries. And also fix the problem here.
Simple is powerful.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking with @bingwang-ms to see if this can be cherry-picked - #1164

#This is ipv6 address
ip_addr = key.replace(key.split(':')[0] + ':' + key.split(':')[1] + ':', '')
neighbor_entries.append((vlan_name, mac, ip_addr))
syslog.syslog(syslog.LOG_INFO, "Neighbor entry: [Vlan: %s, Mac: %s, Ip: %s]" % (vlan_name, mac, ip_addr))

db.close(db.APPL_DB)

with open(filename, 'w') as fp:
json.dump(arp_output, fp, indent=2, separators=(',', ': '))

return arp_entries
return neighbor_entries

def is_mac_unicast(mac):
first_octet = mac.split(':')[0]
Expand Down Expand Up @@ -201,14 +208,19 @@ def send_arp(s, src_mac, src_ip, dst_mac_s, dst_ip_s):

return

def garp_send(arp_entries, map_mac_ip_per_vlan):
def send_ndp(s, src_mac, src_ip, dst_mac_s, dst_ip_s):
#TODO: Implement send in neighbor solicitation format

return

def send_garp_nd(neighbor_entries, map_mac_ip_per_vlan):
ETH_P_ALL = 0x03

# generate source ip addresses for arp packets
src_ip_addrs = {vlan_name:get_iface_ip_addr(vlan_name) for vlan_name,_,_ in arp_entries}
src_ip_addrs = {vlan_name:get_iface_ip_addr(vlan_name) for vlan_name,_,_ in neighbor_entries}

# generate source mac addresses for arp packets
src_ifs = {map_mac_ip_per_vlan[vlan_name][dst_mac] for vlan_name, dst_mac, _ in arp_entries}
src_ifs = {map_mac_ip_per_vlan[vlan_name][dst_mac] for vlan_name, dst_mac, _ in neighbor_entries}
src_mac_addrs = {src_if:get_iface_mac_addr(src_if) for src_if in src_ifs}

# open raw sockets for all required interfaces
Expand All @@ -217,10 +229,13 @@ def garp_send(arp_entries, map_mac_ip_per_vlan):
sockets[src_if] = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETH_P_ALL))
sockets[src_if].bind((src_if, 0))

# send arp packets
for vlan_name, dst_mac, dst_ip in arp_entries:
# send arp/ndp packets
for vlan_name, dst_mac, dst_ip in neighbor_entries:
src_if = map_mac_ip_per_vlan[vlan_name][dst_mac]
send_arp(sockets[src_if], src_mac_addrs[src_if], src_ip_addrs[vlan_name], dst_mac, dst_ip)
if ipaddress.ip_interface(dst_ip).ip.version == 4:
send_arp(sockets[src_if], src_mac_addrs[src_if], src_ip_addrs[vlan_name], dst_mac, dst_ip)
else:
send_ndp(sockets[src_if], src_mac_addrs[src_if], src_ip_addrs[vlan_name], dst_mac, dst_ip)

# close the raw sockets
for s in sockets.values():
Expand Down Expand Up @@ -271,9 +286,9 @@ def main():
print("Target directory '%s' not found" % root_dir)
return 3
all_available_macs, map_mac_ip_per_vlan = generate_fdb_entries(root_dir + '/fdb.json')
arp_entries = generate_arp_entries(root_dir + '/arp.json', all_available_macs)
neighbor_entries = generate_neighbor_entries(root_dir + '/arp.json', all_available_macs)
generate_default_route_entries(root_dir + '/default_routes.json')
garp_send(arp_entries, map_mac_ip_per_vlan)
send_garp_nd(neighbor_entries, map_mac_ip_per_vlan)
return 0

if __name__ == '__main__':
Expand Down