diff --git a/mxrouter/mxrouterctl b/mxrouter/mxrouterctl
index ecc6a441..97135863 100755
--- a/mxrouter/mxrouterctl
+++ b/mxrouter/mxrouterctl
@@ -316,6 +316,56 @@ sub configure_vlans {
 	}
 }
 
+my $want_ipsets;    # { name => [type,filename,create-options]) , ... }
+
+sub ipset {
+	my ($name,$type,$filename,@options)=@_;
+	$want_ipsets->{$name}=[$type,$filename,@options];
+}
+
+sub read_active_ipsets {
+	my $active_ipsets;		# { $name => 1 , ... )
+	open my $p,'-|','ipset','--list','-n' or die "$!";
+	while (<$p>) {
+		chomp;
+		$active_ipsets->{$_}=1;
+	}
+	return $active_ipsets;
+}
+
+sub unconfigure_ipsets {
+	my ($have_ipsets)=@_;
+	for my $name (sort keys %$have_ipsets) {
+		sys('ipset','destroy',$name);
+	}
+}
+
+sub configure_ipsets {
+	my ($want_ipsets)=@_;
+	for my $name (sort keys %$want_ipsets) {
+		my ($type,$filename,@options)=@{$want_ipsets->{$name}};
+		sys('ipset','create',$name,$type,@options);
+	}
+}
+sub reload_ipsets {
+	my ($want_ipsets)=@_;
+	for my $name (sort keys %$want_ipsets) {
+		my ($type,$filename,@options)=@{$want_ipsets->{$name}};
+		my $tmp="$name-TMP";
+		warn "read ipset $name from $filename\n";
+		system('ipset','create',$tmp,$type,@options) and exit 1;
+		$type eq 'hash:ip' or die "read ipset type $type from file not implemented\n";
+		open my $in,'<',$filename or die "$filename: $!\n";
+		while (<$in>) {
+			s/#.*//;
+			/^\s*(\d+\.\d+\.\d+\.\d+)\s*$/ or next;
+			system('ipset','add',$tmp,$1) and exit 1;
+		}
+		system('ipset','swap',$name,$tmp) and exit 1;
+		system('ipset','destroy',$tmp) and exit 1;
+	}
+}
+
 our %radvd;		# ( 'net03' => 'AdvSendAdvert on;prefix 2a02:d480:e08:20::/64;' , ...)
 
 sub radvd {
@@ -358,17 +408,8 @@ sub disable_ipv4_rp_filter {
 	$disable_ipv4_rp_filter{$if}=1;
 }
 
-sub reload_ip_blacklist {
-	sys('ipset','flush','ip-blacklist');
-	if (-e '/etc/local/mxrouter/ip-blacklist') {
-		open my $in,'<','/etc/local/mxrouter/ip-blacklist' or die "/etc/local/mxrouter/ip-blacklist: $!\n";
-		while (<$in>) {
-			s/#.*//;
-			/^\s*(\d+\.\d+\.\d+\.\d+)\s*$/ or next;
-			system('ipset','add','ip-blacklist',$1);
-		}
-	}
-}
+
+
 
 sub start {
 
@@ -494,6 +535,17 @@ sub start {
 		set_ipv4_routing(1);
 	}
 
+	my $have_ipsets=read_active_ipsets();
+	my ($new_ipsets,$del_ipsets)=({},{});
+	for (keys %$want_ipsets) {
+		$new_ipsets->{$_}=$want_ipsets->{$_}
+			unless exists $have_ipsets->{$_};
+	}
+	for (keys %$have_ipsets) {
+		$del_ipsets->{$_} = $have_ipsets->{$_}
+			unless exists $want_ipsets->{$_};
+	}
+
 	stop_process_if($process_ulogd);
 	stop_process_if($process_dhcrelay);
 	stop_process_if($process_radvd);
@@ -530,14 +582,15 @@ sub start {
 	start_process_if($process_dhcrelay);
 	start_process_if($process_radvd);
 
+	configure_ipsets($new_ipsets);
 	unless ($opt_noop) {
-		sys('ipset','create','-exist','ip-blacklist','hash:ip','counters');
-		reload_ip_blacklist();
 		open my $pipe,'|-','iptables-restore' or die "$!\n";
 		print $pipe rules_in_restore_format();
 		close $pipe or die "$!\n";
 		$? and exit 1;
 	}
+	unconfigure_ipsets($del_ipsets);
+	reload_ipsets($want_ipsets);
 }
 
 sub move_dev_into_ns {