CentOS에서는 NetworkManager를 사용하여 인터페이스와 네트워크 구성을 처리합니다. 시연을 위해 스위치의 포트 1에서 포트 2로 네트워크 케이블을 빠르게 연결해야 했습니다. 각 스위치 포트는 서로 다른 네트워크에 속합니다. 각 네트워크에는 해당 네트워크에 IP 주소를 할당하는 별도의 DHCP 서버가 있습니다. 컴퓨터를 스위치의 다른 포트에 연결할 때마다 새 IP 주소를 받아야 합니다.
그러나 케이블을 뽑은 후 인터페이스에서 IP 주소가 제거되는 데 약 5초가 걸립니다. 그래서 컴퓨터를 다른 포트에 다시 연결했는데 이전 IP 주소는 제거되지 않았고 새 IP 주소도 할당되지 않았습니다.
첫 번째 시도는 사용자 정의 스크립트를 사용하여 /etc/NetworkManager/NetworkManager/dispatcher.d/
인터페이스의 IP 주소를 새로 고치는 것이었습니다. 안타깝게도 시간 초과 후 약 5초가 지나서야 내 스크립트가 호출됩니다.
IP 주소를 더 빠르게 새로 고치도록 NetworkManager를 구성할 수 있습니까? 그렇다면 어떻게? NetworkManager를 사용하지 않고 IP 주소를 빠르게 삭제할 수 있는 다른 방법이 있습니까?
또한 이 시간 초과의 원인이 되는 네트워크 스택의 구성 요소를 아는 사람이 있습니까? 줄이는 것이 가능한가요?
답변1
NM은 장치를 비활성화하기 전에 5초 동안 반송파 손실 신호를 무시합니다. 제한 시간은 현재 구성할 수 없습니다(경우에 따라 제한 시간이 10초까지 연장될 수도 있음). 이는 MTU를 변경할 때나 스위치가 그렇게 하기로 결정하는 경우처럼 캐리어가 일시적으로 사라질 수 있기 때문에 수행됩니다.
쉬운 해결책은 모르겠습니다. 케이블을 더 빨리 다시 연결하려면 10초 밖에 걸리지 않습니다. 물론 nmcli device reapply "$DEV"
또는 을 (를) 발행할 수 있지만 nmcli connection up "$CON"
이를 위해서는 사용자의 추가 수동 개입이 필요합니다.
답변2
저는 현재 인터페이스를 직접 관리하기 위해 C로 작성된 서비스를 사용하고 있습니다. 기본적으로 포장지예요dh클라이언트그리고아이피. 인터페이스를 관리하는 데 사용하는 코드는 다음과 같습니다.
#include <stdio.h>
#include <string.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#include <stdlib.h>
#include <stdbool.h>
#define ENTRY(x) {x, #x}
struct {
unsigned flag;
const char *name;
} ifi_flag_map[] = {
ENTRY(IFF_UP),
ENTRY(IFF_BROADCAST),
ENTRY(IFF_DEBUG),
ENTRY(IFF_LOOPBACK),
ENTRY(IFF_POINTOPOINT),
ENTRY(IFF_NOTRAILERS),
ENTRY(IFF_RUNNING),
ENTRY(IFF_NOARP),
ENTRY(IFF_PROMISC),
ENTRY(IFF_ALLMULTI),
ENTRY(IFF_MASTER),
ENTRY(IFF_SLAVE),
ENTRY(IFF_MULTICAST),
ENTRY(IFF_PORTSEL),
ENTRY(IFF_AUTOMEDIA),
ENTRY(IFF_DYNAMIC),
ENTRY(IFF_LOWER_UP),
ENTRY(IFF_DORMANT),
ENTRY(IFF_ECHO),
};
int InterfaceIndex;
char InterfaceName[32];
char FlushCommand[64];
char DHCPCommand[64];
void check_flags(unsigned flags)
{
size_t i;
bool hasFlagLowerUp = false;
for (i = 0; i < sizeof ifi_flag_map/sizeof ifi_flag_map[0]; i++) {
if (flags & ifi_flag_map[i].flag) {
if (ifi_flag_map[i].name == "IFF_LOWER_UP"){
hasFlagLowerUp = true;
}
}
}
if (!hasFlagLowerUp){
printf("Cable removed. Going to flush IPs now...\n");
system(FlushCommand);
} else {
printf("Flag IFF_LOWER_UP present. Going to call %s.\n", DHCPCommand);
system(DHCPCommand);
}
}
void read_msg(int fd)
{
int len;
char buf[4096];
struct iovec iov = { buf, sizeof(buf) };
struct sockaddr_nl sa;
struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
struct nlmsghdr *nh;
len = recvmsg(fd, &msg, 0);
if(len == -1) {
perror("recvmsg");
return;
}
for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
nh = NLMSG_NEXT (nh, len)) {
struct ifinfomsg *ifimsg;
if (nh->nlmsg_type == NLMSG_DONE)
return;
if (nh->nlmsg_type == NLMSG_ERROR) {
continue;
}
ifimsg = NLMSG_DATA(nh);
printf("Noticed event on interface with id %u\n", ifimsg->ifi_index);
if (ifimsg->ifi_index == InterfaceIndex) {
printf("Interface is supervised interface %s. Going to check if cable was removed...\n",InterfaceName);
check_flags(ifimsg->ifi_flags);
}
}
}
int main(int argc, char *argv[])
{
if (argc < 3){
printf("Please provide interface id as first argument\n");
printf("Please provide interface name as second argument\n\n");
printf("Example: %s 2 eth0\n", argv[0]);
return 1;
}
if (sscanf (argv[1], "%i", &InterfaceIndex) != 1) {
fprintf(stderr, "Interface index must be integer\n");
return 1;
}
strcpy(InterfaceName,argv[2]);
sprintf(FlushCommand, "ip addr flush dev %s", InterfaceName);
sprintf(DHCPCommand, "dhclient -r %s && dhclient %s", InterfaceName, InterfaceName);
printf("Watching interface %s with id %u for events.\n", InterfaceName, InterfaceIndex);
printf("Will flush IPs from interface %s when cable is removed.\n", InterfaceName);
struct sockaddr_nl sa;
int fd;
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK;
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(fd == -1) {
perror("socket");
return 1;
}
if(bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
perror("bind");
return 1;
}
for(;;) {
read_msg(fd);
}
return 0;
}