Like others have mentioned, I've noticed this happening while the computer is running and even while the NIC is active (during a large download), so it seems to have nothing to do with power management.
For now, I've written a small C program to restart the NIC if needed.
It's a C program and not a bash script because it needs to be run as root, and shell script no longer respect the sticky bit for security reasons.
You'd need a C compiler to compile it, the easiest way to install the Xcode command line tools is to just type:
gcc in the terminal.
If you don't have it installed, the system should prompt you to install the command line tools.
Once you have a working C compiler (no system is truly whole without one!), do the following in a terminal:
mkdir -p ~/bin # I'm using ~/bin for my local user binaries, feel free to change
cc keep_nic_alive.c -o keep_nic_alive
sudo chown root keep_nic_alive # Make it owned by root
sudo chmod +s keep_nic_alive # Apply the sticky bit, so it would run as root as the euid
sudo mv keep_nic_alive ~/bin/ # Move it to my bin directory
Edit your crontab file:
crontab -e
and add:
* * * * * ~/bin/keep_nic_alive 192.168.0.1 >> ~/keep_nic_alive.log
!!!Change the address to your router's address!!!
The file keep_nic_alive.log in your home directory will log restart attempts.
And finally - here's the code for keep_nic_alive.c:
//
// keep_nic_alive.c
// keep_nic_alive
// Simple program that either receives the current router address or tries to figure it out by itself, ping it and restart en0 if needed.
// See https://discussions.apple.com/thread/252283789 for more info.
// Created by Moshe Gottlieb on 10-Mar-21.
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// Ugly hack!
static char buffer[4096];
/**
Calls a system command, and sets the output to the static buffer variable
Yep, nothing you'd see in a real program.
@param cmd The command to execute
@return Command status code
*/
int _system(const char* cmd){
FILE* f = popen(cmd, "r");
if (!f){
perror("Could not execute shell command");
exit(1);
}
size_t len = fread(buffer,1,sizeof(buffer)-1,f);
if (len && buffer[len-1] == '\n') --len; // trim the last \n that is added for some reason
buffer[len] = '\0'; // Null terminate
return pclose(f); // status code is returned from pclose
}
int main(int argc, const char * argv[]) {
if (geteuid() != 0){
fprintf(stderr,"This program is meant to be run as root\n");
return 1;
}
char router_address[16]; // ipv4 address + dots is 15 characters max
router_address[15] = 0;
if (argc == 2){
strncpy(router_address,argv[1],sizeof(router_address)-1);
} else {
_system("/usr/sbin/netstat -r -n | grep default | /usr/bin/head -n1 | tr -s \" \" | /usr/bin/cut -f2 -d \" \"");
strncpy(router_address,buffer,sizeof(router_address)-1);
}
char cmd[512];
snprintf(cmd, sizeof(cmd), "/sbin/ping -t1 -c1 %s",router_address);
cmd[sizeof(cmd)-1] = 0; // just in case
if (_system(cmd) != 0){ // Houston, we have a problem
printf("Restarting interface en0\n");
setruid(0);
system("/sbin/ifconfig en0 down");
return system("/sbin/ifconfig en0 up");
} else {
return 0;
}
}