@@ -115,6 +115,15 @@ class UBInt64(GenericType):
115115 _fmt = "!Q"
116116
117117
118+ class UBInt128 (GenericType ):
119+ """Format character for an Unsigned Long Long.
120+
121+ Class for an 128-bit (16-byte) Unsigned Integer.
122+ """
123+
124+ _fmt = "!8H"
125+
126+
118127class DPID (GenericType ):
119128 """DataPath ID. Identifies a switch."""
120129
@@ -343,6 +352,114 @@ def __deepcopy__(self, memo):
343352 return IPAddress (address = self ._value , netmask = self .netmask )
344353
345354
355+ class IPv6Address (GenericType ):
356+ """Defines a IPv6 address."""
357+
358+ netmask = UBInt128 ()
359+
360+ def __init__ (self , address = "0000:0000:0000:0000:0000:0000:0000:0000/128" ,
361+ netmask = None ):
362+ """Create an IPv6Address with the parameters below.
363+
364+ Args:
365+ address (str): IP Address using IPv6.
366+ Defaults to '0000:0000:0000:0000:0000:0000:0000:0000/128'
367+ """
368+ if '/' in address :
369+ address , netmask = address .split ('/' )
370+ else :
371+ netmask = 128 if netmask is None else netmask
372+
373+ if address == '::' :
374+ address = '0:0:0:0:0:0:0:0'
375+ elif '::' in address :
376+ temp = address .split (':' )
377+ index = temp .index ('' )
378+ temp = [x for x in temp if x != '' ]
379+ address = temp [:index ] + ['0' ] * (8 - len (temp )) + temp [index :]
380+ address = ':' .join (address )
381+
382+ super ().__init__ (address )
383+ self .netmask = int (netmask )
384+
385+ def pack (self , value = None ):
386+ """Pack the value as a binary representation.
387+
388+ If the value is None the self._value will be used to pack.
389+
390+ Args:
391+ value (str): IP Address with IPv6 format.
392+
393+ Returns:
394+ bytes: The binary representation.
395+
396+ Raises:
397+ struct.error: If the value does not fit the binary format.
398+
399+ """
400+ if isinstance (value , type (self )):
401+ return value .pack ()
402+
403+ if value is None :
404+ value = self ._value
405+
406+ if value .find ('/' ) >= 0 :
407+ value = value .split ('/' )[0 ]
408+
409+ try :
410+ value = value .split (':' )
411+ return struct .pack ('!8H' , * [int (x , 16 ) for x in value ])
412+ except struct .error as err :
413+ msg = "IPv6Address error. "
414+ msg += "Class: {}, struct error: {} " .format (type (value ).__name__ ,
415+ err )
416+ raise exceptions .PackException (msg )
417+
418+ def unpack (self , buff , offset = 0 ):
419+ """Unpack a binary message into this object's attributes.
420+
421+ Unpack the binary value *buff* and update this object attributes based
422+ on the results.
423+
424+ Args:
425+ buff (bytes): Binary data package to be unpacked.
426+ offset (int): Where to begin unpacking.
427+
428+ Raises:
429+ Exception: If there is a struct unpacking error.
430+
431+ """
432+ def _int2hex (number ):
433+ return "{0:0{1}x}" .format (number , 4 )
434+
435+ try :
436+ unpacked_data = struct .unpack ('!8H' , buff [offset :offset + 16 ])
437+ except struct .error as exception :
438+ raise exceptions .UnpackException ('%s; %s: %s' % (exception ,
439+ offset , buff ))
440+
441+ transformed_data = ':' .join ([_int2hex (x ) for x in unpacked_data ])
442+ self ._value = transformed_data
443+
444+ def get_size (self , value = None ):
445+ """Return the IPv6 address size in bytes.
446+
447+ Args:
448+ value: In structs, the user can assign other value instead of
449+ this class' instance. Here, in such cases, ``self`` is a class
450+ attribute of the struct.
451+
452+ Returns:
453+ int: The address size in bytes.
454+
455+ """
456+ return 16
457+
458+ def __deepcopy__ (self , memo ):
459+ """Improve deepcopy speed."""
460+ return IPv6Address (address = self ._value , netmask = self .netmask )
461+
462+
346463class HWAddress (GenericType ):
347464 """Defines a hardware address."""
348465
0 commit comments