From 30d540abfcac1c3ebbb067a606034e2a854ee1a4 Mon Sep 17 00:00:00 2001
From: Bob Gilligan <gilligan@sydney.vyatta.com>
Date: Wed, 12 Dec 2007 10:19:53 -0800
Subject: Bugfix: 2189 Add config node to configure NIC interrupt CPU affinity
 on SMPs.

---
 Makefile.am                                        |   1 +
 scripts/vyatta-irqaffin                            | 139 +++++++++++++++++++++
 .../ethernet/node.tag/smp_affinity/node.def        |   6 +
 3 files changed, 146 insertions(+)
 create mode 100644 scripts/vyatta-irqaffin
 create mode 100644 templates/interfaces/ethernet/node.tag/smp_affinity/node.def

diff --git a/Makefile.am b/Makefile.am
index 733526f..7cde9aa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,6 +37,7 @@ sbin_SCRIPTS  += scripts/vyatta-save-config.pl
 sbin_SCRIPTS  += scripts/vyatta-load-config.pl
 sbin_SCRIPTS  += scripts/vyatta-cfg-notify
 sbin_SCRIPTS  += scripts/vyatta-interfaces.pl
+sbin_SCRIPTS  += scripts/vyatta-irqaffin
 
 share_perl5_DATA = scripts/VyattaConfig.pm
 share_perl5_DATA += scripts/VyattaConfigDOMTree.pm
diff --git a/scripts/vyatta-irqaffin b/scripts/vyatta-irqaffin
new file mode 100644
index 0000000..6650175
--- /dev/null
+++ b/scripts/vyatta-irqaffin
@@ -0,0 +1,139 @@
+#!/bin/bash
+#
+# CLI back-end script to manipulate NIC interrupt CPU affinity.
+#
+# Provides sub-commands to:
+#   - Check the validity of an interface name and affinity mask value
+#   - Set the affinity mask to the IRQ being used by an interface
+#   - Reset the affinity mask of the IRQ being used by an interface to the
+#     system default value of all-ones.
+#   - Print the affinity mask of the IRQ being used by an interface
+#
+
+# The default "all-ones" IRQ affinity mask.  Used in the "reset" sub-command.
+DEFAULT_MASK=ffff
+
+# Max number of hex characters in an IRQ affinity mask.  Support up to 16 CPUs.
+MAX_MASK=4
+
+print_usage()
+{
+    echo "Usage:"
+    echo -e "\t$0 check <ifname> <mask>"
+    echo -e "\t$0 set <ifname> <mask>"
+    echo -e "\t$0 reset <ifname>"
+    echo -e "\t$0 print <ifname>"
+}
+
+get_irqnum()
+{
+    irqnum=`find /proc/irq -name $1 -print | awk -F / '{ print $4 }'`
+    if [ -z "$irqnum" ]; then
+	echo "Invalid interface name: $1"
+	return 1
+    fi
+    return 0
+}
+
+
+get_mask()
+{
+    mask=$1
+    # mask must be a short hex value
+    if [ ${#mask} -gt $MAX_MASK ]; then
+	echo "mask too long: ${#2} characters."
+	return 1
+    fi
+
+    # strip out all the hex digits
+    exmask=`echo $mask | sed -e s/[0-9a-f]//g`
+
+    # if anything is left, its not hex
+    if [ ! -z "$exmask" ]; then
+	echo "Invalid characters in hex mask: $exmask"
+	return 1
+    fi
+    return 0
+}
+
+case "$1" in
+    check)
+	if [ $# -ne 3 ]; then
+		print_usage
+		exit 1
+	fi
+
+	if ! get_irqnum $2 ; then
+	    exit 1
+	fi
+
+	if ! get_mask $3 ; then
+	    exit 1
+	fi
+	exit 0
+	;;
+
+    set)
+	if [ $# -ne 3 ]; then
+		print_usage
+		exit 1
+	fi
+	if ! get_irqnum $2 ; then
+	    exit 1
+	fi
+
+	if ! get_mask $3 ; then
+	    exit 1
+	fi
+
+	echo $mask > /proc/irq/$irqnum/smp_affinity
+
+	if [ $? -ne 0 ]; then
+	    echo "Couldn't assign smp_affinity.  Exit status: $?"
+	    exit 1
+	fi
+	;;
+
+    reset)
+	if [ $# -ne 2 ]; then
+		print_usage
+		exit 1
+	fi
+	if ! get_irqnum $2 ; then
+	    exit 1
+	fi
+
+	echo $DEFAULT_MASK > /proc/irq/$irqnum/smp_affinity
+	if [ $? -ne 0 ]; then
+	    echo "Couldn't assign smp_affinity.  Exit status: $?"
+	    exit 1
+	fi
+	;;
+     
+
+    print)
+	if [ $# -ne 2 ]; then
+		print_usage
+		exit 1
+	fi
+	if ! get_irqnum $2 ; then
+	    exit 1
+	fi
+
+	mask=`cat /proc/irq/$irqnum/smp_affinity`
+	
+	if [ -z $mask ]; then
+	    echo "Couldn't get smp_affinity for interface $2, irq $irqnum"
+	    exit 1
+	fi
+
+	echo "Interface $2 is using IRQ: $irqnum"
+	echo "SMP affinity mask for IRQ $irqnum is: $mask"
+	;;
+
+    *)
+	print_usage
+	exit 1
+	;;
+	
+esac
diff --git a/templates/interfaces/ethernet/node.tag/smp_affinity/node.def b/templates/interfaces/ethernet/node.tag/smp_affinity/node.def
new file mode 100644
index 0000000..b24be8c
--- /dev/null
+++ b/templates/interfaces/ethernet/node.tag/smp_affinity/node.def
@@ -0,0 +1,6 @@
+multi:
+type: txt
+help: "Set CPU interrupt affinity mask for this interface"
+syntax: exec "/opt/vyatta/sbin/vyatta-irqaffin check $(../@) $(@)"
+create: "sudo /opt/vyatta/sbin/vyatta-irqaffin set $(../@) $(@)"; "Error setting CPU affinity mask $(@) on interface $(../@)"
+delete: "sudo /opt/vyatta/sbin/vyatta-irqaffin reset (../@)"; "Error deleting CPU affinity mask on interface $(../@)"
-- 
cgit v1.2.3


From 359eedef503b1577516a17b012e29c18c1f51e26 Mon Sep 17 00:00:00 2001
From: An-Cheng Huang <ancheng@vyatta.com>
Date: Wed, 19 Dec 2007 17:30:36 -0800
Subject: fix for bug 2540: make variables read-write

---
 etc/default/vyatta-cfg | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/etc/default/vyatta-cfg b/etc/default/vyatta-cfg
index e560788..dfb4006 100644
--- a/etc/default/vyatta-cfg
+++ b/etc/default/vyatta-cfg
@@ -7,13 +7,14 @@ declare -x -r VYATTA_CHANGES_ONLY_DIR=${vyatta_configdir}/tmp/changes_only_$$
 declare -x -r VYATTA_TEMP_CONFIG_DIR=${vyatta_configdir}/tmp/new_config_$$
 declare -x -r VYATTA_CONFIG_TMP=${vyatta_configdir}/tmp/tmp_$$
 declare -x -r VYATTA_CONFIG_TEMPLATE=$vyatta_cfg_templates
-declare -x -r VYATTA_EDIT_LEVEL=/
-declare -x -r VYATTA_TEMPLATE_LEVEL=/
 declare -x -r VYATTA_TAG_NAME=node.tag
 declare -x -r VYATTA_MOD_NAME=.modified
 declare -x -r VYATTA_CFG_GROUP_NAME=vyattacfg
 } 2>/dev/null || :
 
+declare -x VYATTA_EDIT_LEVEL=/
+declare -x VYATTA_TEMPLATE_LEVEL=/
+
 # don't set level if already set
 if [ -n "$VYATTA_USER_LEVEL_DIR" ]; then
   return
-- 
cgit v1.2.3


From 7f55b537ee7e0c5f0867cd40764693c2c711c228 Mon Sep 17 00:00:00 2001
From: Stig Thormodsrud <stig@vyatta.com>
Date: Wed, 19 Dec 2007 17:51:16 -0800
Subject: Update to fairfield version of script.

---
 scripts/VyattaMisc.pm | 196 +++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 148 insertions(+), 48 deletions(-)

diff --git a/scripts/VyattaMisc.pm b/scripts/VyattaMisc.pm
index 61c646b..e77bb3b 100755
--- a/scripts/VyattaMisc.pm
+++ b/scripts/VyattaMisc.pm
@@ -1,62 +1,162 @@
+#
+# Module: VyattaMisc.pm
+#
+# **** License ****
+# Version: VPL 1.0
+#
+# The contents of this file are subject to the Vyatta Public License
+# Version 1.0 ("License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.vyatta.com/vpl
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2005, 2006, 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Marat
+# Date: 2007
+# Description:
+#
+# **** End License ****
+#
+
 package VyattaMisc;
-require Exporter;
-@ISA	= qw(Exporter);
-@EXPORT	= qw(getNetAddIP, isIpAddress);
-@EXPORT_OK = qw(getNetAddIP, isIpAddress);
 
 use strict;
 
+use VyattaConfig;
+
 sub getNetAddrIP {
-  my ($interface);
-  ($interface) = @_;
-
-  if ($interface eq '') {
-    print STDERR "Error:  No interface specified.\n";
-    return undef;
-  }
-
-
-  my $ifconfig_out = `ifconfig $interface`;
-  $ifconfig_out =~ /inet addr:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/;
-  my $ip = $1;
-  if ($ip eq '') {
-    print STDERR "Error:  Unable to determine IP address for interface \'$interface\'.\n";
-    return undef;
-  }
-
-
-  $ifconfig_out =~ /Mask:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/;
-  my $netmask = $1;
-  if ($netmask eq '') {
-    print STDERR "Error:  Unable to determine netmask for interface \'$interface\'.\n";
-    return undef;
-  }
-
-  use NetAddr::IP;  # This library is available via libnetaddr-ip-perl.deb
-  my $naip = new NetAddr::IP($ip, $netmask);
-  return $naip;
-}
+    my ($interface);
+    ($interface) = @_;
+
+    if ($interface eq '') {
+	print STDERR "Error:  No interface specified.\n";
+	return undef;
+    }
 
-sub isIpAddress {
-  my $ip = shift;
+    my $ifconfig_out = `ifconfig $interface`;
+    $ifconfig_out =~ /inet addr:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/;
+    my $ip = $1;
+    if ($ip eq '') {
+	print STDERR "Error:  Unable to determine IP address for interface \'$interface\'.\n";
+	return undef;
+    }
+
+    $ifconfig_out =~ /Mask:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/;
+    my $netmask = $1;
+    if ($netmask eq '') {
+	print STDERR "Error:  Unable to determine netmask for interface \'$interface\'.\n";
+	return undef;
+    }
+    
+    use NetAddr::IP;  # This library is available via libnetaddr-ip-perl.deb
+    my $naip = new NetAddr::IP($ip, $netmask);
+    return $naip;
+}
 
-  $_ = $ip;
-  if ( ! /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
+sub isClusterIP {
+    my ($vc, $ip) = @_;
+    
+    if (!(defined($ip))) {
+	return 0;
+    }
+    
+    my @cluster_groups = $vc->listNodes('cluster group');
+    foreach my $cluster_group (@cluster_groups) {
+	my @services = $vc->returnValues("cluster group $cluster_group service");
+	foreach my $service (@services) {
+	    if ($ip eq $service) {
+		return 1;
+	    }
+	}
+    }
+    
     return 0;
-  }
-  else {
-    my @ips = split /\./, $ip;
-    my $octet = 0;
-    my $counter = 0;
+}
 
-    foreach $octet (@ips) {
-      if (($octet < 0) || ($octet > 255)) { return 0; }
-      if (($counter == 0) && ($octet < 1)) { return 0; }
-      $counter++;
+sub isIPinInterfaces {
+    my ($vc, $interfaces, $local_ip) = @_;
+
+    if (!(defined($local_ip))) {
+	return 0;
     }
-  }
 
-  return 1;
+    my @ethernets = $vc->listNodes('interfaces ethernet');
+    foreach my $ethernet (@ethernets) {
+	if (defined($interfaces->{$ethernet})) {
+	    my @addresses = $vc->listNodes("interfaces ethernet $ethernet address");
+	    my %addresses_hash = map { $_ => 1 } @addresses;
+	    if (defined($addresses_hash{$local_ip})) {
+		return 1;
+	    }
+	    
+	    my @vifs = $vc->listNodes("interfaces ethernet $ethernet vif");
+	    foreach my $vif (@vifs) {
+		my @addresses_vif = $vc->listNodes("interfaces ethernet $ethernet vif $vif address");
+		my %addresses_vif_hash = map { $_ => 1 } @addresses_vif;
+		if (defined($addresses_vif_hash{$local_ip})) {
+		    return 1;
+		}
+		
+		my $virtual_address = $vc->returnValue("interfaces ethernet $ethernet vif $vif vrrp virtual-address");
+		if (defined($virtual_address) && $virtual_address eq $local_ip) {
+		    return 1;
+		}
+	    }
+	    
+	    my $virtual_address = $vc->returnValue("interfaces ethernet $ethernet vrrp virtual-address");
+	    if (defined($virtual_address) && $virtual_address eq $local_ip) {
+		return 1;
+	    }
+	}
+    }
+    
+    my @serials = $vc->listNodes('interfaces serial');
+    foreach my $serial (@serials) {
+	if (defined($interfaces->{$serial})) {
+	    my @ppp_vifs = $vc->listNodes("interfaces serial $serial ppp vif");
+	    foreach my $ppp_vif (@ppp_vifs) {
+		my $local_address = $vc->returnValue("interfaces serial $serial ppp vif $ppp_vif address local-address");
+		if (defined($local_address) && $local_address eq $local_ip) {
+		    return 1;
+		}
+	    }
+	    
+	    my @cisco_hdlc_vifs = $vc->listNodes("interfaces serial $serial cisco-hdlc vif");
+	    foreach my $cisco_hdlc_vif (@cisco_hdlc_vifs) {
+		my $local_address = $vc->returnValue("interfaces serial $serial cisco-hdlc vif $cisco_hdlc_vif address local-address");
+		if (defined($local_address) && $local_address eq $local_ip) {
+		    return 1;
+		}
+	    }
+	    
+	    my @frame_relay_vifs = $vc->listNodes("interfaces serial $serial frame-relay vif");
+	    foreach my $frame_relay_vif (@frame_relay_vifs) {
+		my $local_address = $vc->returnValue("interfaces serial $serial frame-relay vif $frame_relay_vif address local-address");
+		if (defined($local_address) && $local_address eq $local_ip) {
+		    return 1;
+		}
+	    }
+	}
+    }
+    
+    return 0;
+}
+
+sub isClusteringEnabled {
+    my ($vc) = @_;
+    
+    if ($vc->exists('cluster')) {
+	return 1;
+    } else {
+	return 0;
+    } 
 }
 
 return 1;
-- 
cgit v1.2.3


From 42e3893766f215c7ece78a779c2f680507ae7801 Mon Sep 17 00:00:00 2001
From: An-Cheng Huang <ancheng@vyatta.com>
Date: Wed, 19 Dec 2007 18:30:44 -0800
Subject: check for quotes when loading nodes with multiple values.

---
 scripts/VyattaConfigLoad.pm | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/VyattaConfigLoad.pm b/scripts/VyattaConfigLoad.pm
index eae2946..efec951 100755
--- a/scripts/VyattaConfigLoad.pm
+++ b/scripts/VyattaConfigLoad.pm
@@ -209,7 +209,7 @@ sub findDeletedValues {
     # for "multi:" nodes, need to sort the values by the original order.
     my @nvals = getSortedMultiValues($new_ref, \@active_path);
     if ($is_text) {
-      @nvals = map { /^"(.*)"$/; $1; } @nvals;
+      @nvals = map { /^"(.*)"$/ ? $1 : $_ }@nvals;
     }
     my @ovals = $active_cfg->returnOrigValues('');
     my %comp_hash = $active_cfg->compareValueLists(\@ovals, \@nvals);
@@ -261,7 +261,7 @@ sub findSetValues {
     # for "multi:" nodes, need to sort the values by the original order.
     my @nvals = getSortedMultiValues($new_ref, \@active_path);
     if ($is_text) {
-      @nvals = map { /^"(.*)"$/; $1; } @nvals;
+      @nvals = map { /^"(.*)"$/ ? $1 : $_ } @nvals;
     }
     my @ovals = $active_cfg->returnOrigValues('');
     my %comp_hash = $active_cfg->compareValueLists(\@ovals, \@nvals);
-- 
cgit v1.2.3


From 5e65fbf9c219f025ed9df853e8ceba03f92c1643 Mon Sep 17 00:00:00 2001
From: Stig Thormodsrud <stig@vyatta.com>
Date: Thu, 20 Dec 2007 16:35:07 -0800
Subject: Fix isIPinInterface().

---
 scripts/VyattaMisc.pm | 121 ++++++++++++++++++++++++++++----------------------
 1 file changed, 69 insertions(+), 52 deletions(-)

diff --git a/scripts/VyattaMisc.pm b/scripts/VyattaMisc.pm
index e77bb3b..48b3aa7 100755
--- a/scripts/VyattaMisc.pm
+++ b/scripts/VyattaMisc.pm
@@ -80,68 +80,85 @@ sub isClusterIP {
     return 0;
 }
 
+sub remove_ip_prefix {
+    my @addr_nets = @_;
+
+    s/\/\d+$//  for @addr_nets;    
+    return @addr_nets;
+}
+
+sub is_ip_in_list {
+    my ($ip, @list) = @_;
+    
+    if (!defined($ip) || scalar(@list) == 0) {
+	return 0;
+    }
+
+    @list = remove_ip_prefix(@list);
+    my %list_hash = map { $_ => 1 } @list;
+    if (defined($list_hash{$ip})) {
+	return 1;
+    } else {
+	return 0;
+    }
+}
+
+sub get_eth_ip_addrs {
+    my ($vc, $eth_path) = @_;
+
+    my @addrs      = ();
+    my @virt_addrs = ();
+
+    $vc->setLevel("interfaces ethernet $eth_path");
+    @addrs = $vc->returnValues("address");
+
+    #
+    # check for VIPs
+    #
+    $vc->setLevel("interfaces ethernet $eth_path vrrp vrrp-group");
+    my @vrrp_groups = $vc->listNodes();
+    foreach my $group (@vrrp_groups) {
+	$vc->setLevel("interfaces ethernet $eth_path vrrp vrrp-group $group");
+	@virt_addrs = $vc->returnValues("virtual-address");
+    }
+    return (@addrs, @virt_addrs);
+}
+
+sub get_serial_ip_addrs {
+    #
+    # Todo when serial is added
+    #
+}
+
 sub isIPinInterfaces {
-    my ($vc, $interfaces, $local_ip) = @_;
+    my ($vc, $ip_addr, @interfaces) = @_;
 
-    if (!(defined($local_ip))) {
+    if (!(defined($ip_addr))) {
 	return 0;
     }
 
-    my @ethernets = $vc->listNodes('interfaces ethernet');
-    foreach my $ethernet (@ethernets) {
-	if (defined($interfaces->{$ethernet})) {
-	    my @addresses = $vc->listNodes("interfaces ethernet $ethernet address");
-	    my %addresses_hash = map { $_ => 1 } @addresses;
-	    if (defined($addresses_hash{$local_ip})) {
+    foreach my $intf (@interfaces) {
+	# regular ethernet
+	if ($intf =~ m/^eth\d+$/) {
+	    my @addresses = get_eth_ip_addrs($vc, $intf);
+	    if (is_ip_in_list($ip_addr, @addresses)) {
 		return 1;
 	    }
-	    
-	    my @vifs = $vc->listNodes("interfaces ethernet $ethernet vif");
-	    foreach my $vif (@vifs) {
-		my @addresses_vif = $vc->listNodes("interfaces ethernet $ethernet vif $vif address");
-		my %addresses_vif_hash = map { $_ => 1 } @addresses_vif;
-		if (defined($addresses_vif_hash{$local_ip})) {
-		    return 1;
-		}
-		
-		my $virtual_address = $vc->returnValue("interfaces ethernet $ethernet vif $vif vrrp virtual-address");
-		if (defined($virtual_address) && $virtual_address eq $local_ip) {
-		    return 1;
-		}
-	    }
-	    
-	    my $virtual_address = $vc->returnValue("interfaces ethernet $ethernet vrrp virtual-address");
-	    if (defined($virtual_address) && $virtual_address eq $local_ip) {
+	}
+	# ethernet vlan
+	if ($intf =~ m/^eth(\d+).(\d+)$/) {
+	    my $eth = "eth$1";
+	    my $vif = $2;
+	    my @addresses = get_eth_ip_addrs($vc, "$eth vif $vif");
+	    if (is_ip_in_list($ip_addr, @addresses)) {
 		return 1;
 	    }
 	}
-    }
-    
-    my @serials = $vc->listNodes('interfaces serial');
-    foreach my $serial (@serials) {
-	if (defined($interfaces->{$serial})) {
-	    my @ppp_vifs = $vc->listNodes("interfaces serial $serial ppp vif");
-	    foreach my $ppp_vif (@ppp_vifs) {
-		my $local_address = $vc->returnValue("interfaces serial $serial ppp vif $ppp_vif address local-address");
-		if (defined($local_address) && $local_address eq $local_ip) {
-		    return 1;
-		}
-	    }
-	    
-	    my @cisco_hdlc_vifs = $vc->listNodes("interfaces serial $serial cisco-hdlc vif");
-	    foreach my $cisco_hdlc_vif (@cisco_hdlc_vifs) {
-		my $local_address = $vc->returnValue("interfaces serial $serial cisco-hdlc vif $cisco_hdlc_vif address local-address");
-		if (defined($local_address) && $local_address eq $local_ip) {
-		    return 1;
-		}
-	    }
-	    
-	    my @frame_relay_vifs = $vc->listNodes("interfaces serial $serial frame-relay vif");
-	    foreach my $frame_relay_vif (@frame_relay_vifs) {
-		my $local_address = $vc->returnValue("interfaces serial $serial frame-relay vif $frame_relay_vif address local-address");
-		if (defined($local_address) && $local_address eq $local_ip) {
-		    return 1;
-		}
+	# serial
+	if ($intf =~ m/^wan(\d+).(\d+)$/) {
+	    my @addresses = get_serial_ip_addrs($vc, $intf);
+	    if (is_ip_in_list($ip_addr, @addresses)) {
+		return 1;
 	    }
 	}
     }
-- 
cgit v1.2.3


From 07c75b9c792b8ff48d07de77628c3619893eaf74 Mon Sep 17 00:00:00 2001
From: An-Cheng Huang <ancheng@vyatta.com>
Date: Thu, 20 Dec 2007 17:23:29 -0800
Subject: fix for bug 2340: detecting "deleted" nodes now does not depend on
 "whiteouts" created by unionfs.

---
 scripts/VyattaConfig.pm | 58 +++++--------------------------------------------
 1 file changed, 6 insertions(+), 52 deletions(-)

diff --git a/scripts/VyattaConfig.pm b/scripts/VyattaConfig.pm
index 4d0a90c..03869dc 100644
--- a/scripts/VyattaConfig.pm
+++ b/scripts/VyattaConfig.pm
@@ -268,58 +268,12 @@ sub isDeleted {
 # return array of deleted nodes in the "level"
 # "level" defaults to current
 sub listDeleted {
-  my ($self, $node) = @_;
-  my @return = ();
-  my $filepath = undef;
-  my $curpath = undef;
-  my @nodes = ();
-  my @curnodes = ();
-
-  # setup the entire path with the new level
-  # use the change_dir
-  $node =~ s/\//%2F/g;
-  $node =~ s/\s+/\//g;
-  $filepath = "$self->{_changes_only_dir_base}$self->{_current_dir_level}/$node/";
-  
-  $curpath = "$self->{_active_dir_base}$self->{_current_dir_level}/$node/";
-
-  # let's see if the directory exists and find the the whiteout files
-  if (! -d "$filepath") { return undef; }
-  else {
-    opendir DIR, "$filepath" or return undef;
-    @nodes = grep !/^\.wh\.\.wh\./, grep /^\.wh./, readdir DIR;
-    closedir DIR;
-  }
-
-  if (! -d "$curpath") {
-    return undef;
-  } else {
-    opendir DIR, "$curpath" or return undef;
-    @curnodes = grep !/^\./, readdir DIR;
-    closedir DIR;
-  }
-
-  # get rid of the whiteout prefix
-  my $dir_opq = 0;
-  foreach $node (@nodes) {
-    $node =~ s/^\.wh\.(.+)/$1/;
-    $_ = $node;
-    if (! /__dir_opaque/) {
-      push @return, $node; 
-    } else {
-      $dir_opq = 1;
-    }
-  }
-
-  if ($dir_opq) {
-    # if this node is "dir_opaque", it has been deleted and re-added.
-    # add all nodes in "active" to the return list (so that they will be
-    # marked "deleted"). note that if a node is also re-added, its status
-    # will be changed after the listDeleted call.
-    push @return, @curnodes;
-  }
-
-  return @return;
+  my ($self, $path) = @_;
+  my @new_nodes = $self->listNodes("$path");
+  my @orig_nodes = $self->listOrigNodes("$path");
+  my %new_hash = map { $_ => 1 } @new_nodes;
+  my @deleted = grep { !defined($new_hash{$_}) } @orig_nodes;
+  return @deleted;
 }
 
 ## isChanged("node")
-- 
cgit v1.2.3


From ab19102a564790b94c1919430fbdeb38a8c23377 Mon Sep 17 00:00:00 2001
From: An-Cheng Huang <ancheng@vyatta.com>
Date: Thu, 20 Dec 2007 17:26:50 -0800
Subject: Fixed 'isDeleted' method, related to Bug 2340 fix.

---
 scripts/VyattaConfig.pm | 27 +++++++++------------------
 1 file changed, 9 insertions(+), 18 deletions(-)

diff --git a/scripts/VyattaConfig.pm b/scripts/VyattaConfig.pm
index 03869dc..ecaf545 100644
--- a/scripts/VyattaConfig.pm
+++ b/scripts/VyattaConfig.pm
@@ -241,27 +241,18 @@ sub existsOrig {
 # is the "node" deleted. node is relative.  returns true or false
 sub isDeleted {
   my ($self, $node) = @_;
-  my $endnode = undef;
-  my $filepath = undef;
-  my @nodes = ();
-
-  # split the string into an array
-  (@nodes) = split /\s+/, $node;
-
-  # take the last node off the string
-  $endnode = pop @nodes;
-  # and modify it to match the whiteout name
-  $endnode = ".wh.$endnode";
-
-  # setup the path with the rest of the nodes
-  # use the change_dir
   $node =~ s/\//%2F/g;
   $node =~ s/\s+/\//g;
-  $filepath = "$self->{_changes_only_dir_base}$self->{_current_dir_level}/$node";
 
-  # if the file exists, the node was deleted
-  if (-f "$filepath") { return 1; }
-  else  { return 0; }
+  my $filepathAct
+    = "$self->{_active_dir_base}$self->{_current_dir_level}/$node";
+  my $filepathNew
+    = "$self->{_new_config_dir_base}$self->{_current_dir_level}/$node";
+
+  if ((-e $filepathAct) && !(-e $filepathNew)) {
+    return 1;
+  }
+  return 0;
 }
 
 ## listDeleted("level")
-- 
cgit v1.2.3


From 68df52c1edbf843e6fb56de3578f18fba80799c4 Mon Sep 17 00:00:00 2001
From: An-Cheng Huang <ancheng@vyatta.com>
Date: Thu, 20 Dec 2007 17:28:47 -0800
Subject: This loop should not be iterating over deleted nodes. Related to Bug
 2340.

---
 scripts/VyattaConfig.pm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/VyattaConfig.pm b/scripts/VyattaConfig.pm
index ecaf545..6f99329 100644
--- a/scripts/VyattaConfig.pm
+++ b/scripts/VyattaConfig.pm
@@ -330,9 +330,9 @@ sub listNodeStatus {
   foreach $node (@nodes) {
     if ($node =~ /.+/) {
       #print "DEBUG VyattaConfig->listNodeStatus(): node $node\n";
+      # No deleted nodes -- added, changed, ot static only.
       if    ($self->isAdded("$path $node"))   { $nodehash{$node} = "added"; }
       elsif ($self->isChanged("$path $node")) { $nodehash{$node} = "changed"; }
-      elsif ($self->isDeleted("$path $node")) { $nodehash{$node} = "deleted"; }
       else { $nodehash{$node} = "static"; }
     }
   }
-- 
cgit v1.2.3


From aac164fc48911b10e09b8d562e21aef90bad9699 Mon Sep 17 00:00:00 2001
From: An-Cheng Huang <ancheng@vyatta.com>
Date: Thu, 20 Dec 2007 17:32:19 -0800
Subject: Some checks for undefined references

---
 scripts/VyattaConfig.pm | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/scripts/VyattaConfig.pm b/scripts/VyattaConfig.pm
index 6f99329..3a24579 100644
--- a/scripts/VyattaConfig.pm
+++ b/scripts/VyattaConfig.pm
@@ -190,8 +190,8 @@ sub returnOrigValue {
 # node is relative
 sub returnValues {
   my $val = returnValue(@_);
-  my @values;
-  if ($val) {
+  my @values = ();
+  if (defined($val)) {
     @values = split("\n", $val);
   }
   return @values;
@@ -317,17 +317,16 @@ sub listNodeStatus {
   my ($self, $path) = @_;
   my @nodes = ();
   my %nodehash = ();
-  my $node = undef;
 
   # find deleted nodes first
   @nodes = $self->listDeleted("$path");
-  foreach $node (@nodes) {
+  foreach my $node (@nodes) {
     if ($node =~ /.+/) { $nodehash{$node} = "deleted" };
   }
 
   @nodes = ();
   @nodes = $self->listNodes("$path");
-  foreach $node (@nodes) {
+  foreach my $node (@nodes) {
     if ($node =~ /.+/) {
       #print "DEBUG VyattaConfig->listNodeStatus(): node $node\n";
       # No deleted nodes -- added, changed, ot static only.
-- 
cgit v1.2.3


From 67aa6f38631f725e90dce71fb1ed59cb8ed7ac63 Mon Sep 17 00:00:00 2001
From: An-Cheng Huang <ancheng@vyatta.com>
Date: Thu, 20 Dec 2007 17:35:21 -0800
Subject: Added method 'isChangedOrDeleted'.  Part of Bug 2324 fix.

---
 scripts/VyattaConfig.pm | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/scripts/VyattaConfig.pm b/scripts/VyattaConfig.pm
index 3a24579..6c37073 100644
--- a/scripts/VyattaConfig.pm
+++ b/scripts/VyattaConfig.pm
@@ -283,6 +283,32 @@ sub isChanged {
   else { return 0; }
 }
 
+## isChangedOrDeleted("node")
+# is the "node" changed or deleted. node is relative.  returns true or false
+sub isChangedOrDeleted {
+  my ($self, $node) = @_;
+
+  $node =~ s/\//%2F/g;
+  $node =~ s/\s+/\//g;
+
+  my $filepathChg
+    = "$self->{_changes_only_dir_base}$self->{_current_dir_level}/$node";
+  if (-e $filepathChg) {
+    return 1;
+  }
+
+  my $filepathAct
+    = "$self->{_active_dir_base}$self->{_current_dir_level}/$node";
+  my $filepathNew
+    = "$self->{_new_config_dir_base}$self->{_current_dir_level}/$node";
+
+  if ((-e $filepathAct) && !(-e $filepathNew)) {
+    return 1;
+  }
+
+  return 0;
+}
+
 ## isAdded("node")
 # will compare the new_config_dir to the active_dir to see if the "node" has 
 # been added.  returns true or false.
-- 
cgit v1.2.3


From 60fddb5cba5a7d2eb33ba5f77901b71c58ad462a Mon Sep 17 00:00:00 2001
From: Stig Thormodsrud <stig@vyatta.com>
Date: Thu, 20 Dec 2007 20:35:52 -0800
Subject: Fix broken bgp in glendale.

---
 scripts/VyattaMisc.pm | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/scripts/VyattaMisc.pm b/scripts/VyattaMisc.pm
index 48b3aa7..abb5fbb 100755
--- a/scripts/VyattaMisc.pm
+++ b/scripts/VyattaMisc.pm
@@ -26,6 +26,11 @@
 #
 
 package VyattaMisc;
+require Exporter;
+@ISA	= qw(Exporter);
+@EXPORT	= qw(getNetAddIP isIpAddress);
+@EXPORT_OK = qw(getNetAddIP isIpAddress);
+
 
 use strict;
 
@@ -60,6 +65,28 @@ sub getNetAddrIP {
     return $naip;
 }
 
+sub isIpAddress {
+  my $ip = shift;
+
+  $_ = $ip;
+  if ( ! /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
+    return 0;
+  }
+  else {
+    my @ips = split /\./, $ip;
+    my $octet = 0;
+    my $counter = 0;
+
+    foreach $octet (@ips) {
+      if (($octet < 0) || ($octet > 255)) { return 0; }
+      if (($counter == 0) && ($octet < 1)) { return 0; }
+      $counter++;
+    }
+  }
+
+  return 1;
+}
+
 sub isClusterIP {
     my ($vc, $ip) = @_;
     
-- 
cgit v1.2.3


From d5b3e4d3c413cbf1a5295e51750258d014478857 Mon Sep 17 00:00:00 2001
From: Stig Thormodsrud <stig@vyatta.com>
Date: Wed, 2 Jan 2008 18:06:54 -0800
Subject: - Allow vpn to be configured on a tunnel interface.

---
 scripts/VyattaMisc.pm | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/scripts/VyattaMisc.pm b/scripts/VyattaMisc.pm
index abb5fbb..45bd7d4 100755
--- a/scripts/VyattaMisc.pm
+++ b/scripts/VyattaMisc.pm
@@ -151,6 +151,27 @@ sub get_eth_ip_addrs {
     return (@addrs, @virt_addrs);
 }
 
+sub get_tun_ip_addrs {
+    my ($vc, $tun_path) = @_;
+
+    my @addrs      = ();
+    my @virt_addrs = ();
+
+    $vc->setLevel("interfaces tunnel $tun_path");
+    @addrs = $vc->returnValues("address");
+
+    #
+    # check for VIPs
+    #
+    $vc->setLevel("interfaces tunnel $tun_path vrrp vrrp-group");
+    my @vrrp_groups = $vc->listNodes();
+    foreach my $group (@vrrp_groups) {
+	$vc->setLevel("interfaces tunnel $tun_path vrrp vrrp-group $group");
+	@virt_addrs = $vc->returnValues("virtual-address");
+    }
+    return (@addrs, @virt_addrs);
+}
+
 sub get_serial_ip_addrs {
     #
     # Todo when serial is added
@@ -181,6 +202,13 @@ sub isIPinInterfaces {
 		return 1;
 	    }
 	}
+	# tunnel
+        if ($intf =~ m/^tun\d+$/) {
+	    my @addresses = get_tun_ip_addrs($vc, $intf);
+	    if (is_ip_in_list($ip_addr, @addresses)) {
+		return 1;
+	    }
+	}
 	# serial
 	if ($intf =~ m/^wan(\d+).(\d+)$/) {
 	    my @addresses = get_serial_ip_addrs($vc, $intf);
-- 
cgit v1.2.3