From f9886db053536ff84f6d4a34354abf7be27a970b Mon Sep 17 00:00:00 2001 From: jbjohnso Date: Sat, 17 Mar 2012 19:59:52 +0000 Subject: [PATCH] Rework SLP.pm to do each srvtype as a distinct packet, now mandate caller to specifiy srvtypes. Problem being that SLP hashed multicast addresses don't pan out so well if not very precise git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@11885 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- perl-xCAT/xCAT/SLP.pm | 75 ++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/perl-xCAT/xCAT/SLP.pm b/perl-xCAT/xCAT/SLP.pm index c40e832a9..e9ccb1237 100644 --- a/perl-xCAT/xCAT/SLP.pm +++ b/perl-xCAT/xCAT/SLP.pm @@ -1,4 +1,5 @@ package xCAT::SLP; +use Carp; use strict; my $ip6support = eval { require IO::Socket::INET6; @@ -10,37 +11,37 @@ unless ($ip6support) { require IO::Socket::INET; } -my $defaultsrvtypes = "service:management-hardware.IBM"; #TODO: somehow get at system headers to get the value, put in linux's for now use constant IPV6_MULTICAST_IF => 17; -sub getmulticasthashes { - my %args = @_; - my $srvtypes; - if ($args{SrvTypes}) { - $srvtypes = $args{SrvTypes}; - } else { - $srvtypes = $defaultsrvtypes; +sub getmulticasthash { + my $hash=0; + my @nums = unpack("C*",shift); + foreach my $num (@nums) { + $hash *= 33; + $hash += $num; + $hash &= 0xffff; } - my @types = split /,/,$srvtypes; - my @hashes; - foreach (@types) { - my $hash=0; - my @nums = unpack("C*",$_); - foreach my $num (@nums) { - $hash *= 33; - $hash += $num; - $hash &= 0xffff; - } - $hash &= 0x3ff; - $hash |= 0x1000; - push @hashes,sprintf("%04x",$hash); - } - return @hashes; + $hash &= 0x3ff; + $hash |= 0x1000; + return sprintf("%04x",$hash); } sub dodiscover { + my %args = @_; + unless ($args{SrvTypes}) { croak "SrvTypes argument is required for xCAT::SLP::Dodiscover"; } + my @srvtypes; + if (ref $args{SrvTypes}) { + @srvtypes = @{$args{SrvTypes}}; + } else { + @srvtypes = split /,/,$args{SrvTypes}; + } + foreach my $srvtype (@srvtypes) { + dodiscover_single(%args,SrvType=>$srvtype); + } +} +sub dodiscover_single { my %args = @_; my $packet = gendiscover(%args); my @interfaces = get_interfaces(%args); @@ -52,21 +53,18 @@ sub dodiscover { } else { die "TODO: SLP without ipv6"; } - my @v6addrs; + my $v6addr; if ($ip6support) { - foreach my $hash (getmulticasthashes(%args)) { - my $target = "ff02::1:$hash"; - my ($fam, $type, $proto, $addr, $name) = - Socket6::getaddrinfo($target,"svrloc",Socket6::AF_INET6(),SOCK_DGRAM,0); - push @v6addrs,$addr; - } + my $hash=getmulticasthash($args{SrvType}); + my $target = "ff02::1:$hash"; + my ($fam, $type, $proto, $name); + ($fam, $type, $proto, $v6addr, $name) = + Socket6::getaddrinfo($target,"svrloc",Socket6::AF_INET6(),SOCK_DGRAM,0); } foreach my $iface (@interfaces) { if ($ip6support) { setsockopt($socket,Socket6::IPPROTO_IPV6(),IPV6_MULTICAST_IF,pack("I",$iface)); - foreach my $v6addr (@v6addrs) { - $socket->send($packet,0,$v6addr); - } + $socket->send($packet,0,$v6addr); } #TODO: IPv4 support # setsockopt($socket,IPPROTO_IP,IP_MULTICAST_IF, @@ -103,19 +101,14 @@ sub get_interfaces { # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ sub gendiscover { my %args = @_; - my $srvtypes; - if ($args{SrvTypes}) { - $srvtypes = $args{SrvTypes}; - } else { - $srvtypes = $defaultsrvtypes; - } + my $srvtype = $args{SrvType}; my $scope = "DEFAULT"; if ($args{Scopes}) { $scope = $args{Scopes}; } my $packet = pack("C*",0,0); #start with PRList, we have no prlist so zero #TODO: actually accumulate PRList, particularly between IPv4 and IPv6 runs - my $length = length($srvtypes); + my $length = length($srvtype); $packet .= pack("C*",($length>>8),($length&0xff)); - $packet .= $srvtypes; + $packet .= $srvtype; $length = length($scope); $packet .= pack("C*",($length>>8),($length&0xff)); $packet .= $scope;