77use slog:: { debug, error, trace} ;
88use std:: collections:: BTreeMap ;
99use std:: fmt;
10- use std:: net:: { Ipv4Addr , Ipv6Addr } ;
10+ use std:: net:: { IpAddr , Ipv4Addr , Ipv6Addr } ;
1111use std:: ops:: Bound ;
1212
1313use crate :: Switch ;
@@ -413,6 +413,19 @@ pub fn get_ipv4_mapping(
413413 Err ( DpdError :: Missing ( "no mapping" . into ( ) ) )
414414}
415415
416+ pub fn set_mapping (
417+ switch : & Switch ,
418+ nat_ip : IpAddr ,
419+ low : u16 ,
420+ high : u16 ,
421+ tgt : NatTarget ,
422+ ) -> DpdResult < ( ) > {
423+ match nat_ip {
424+ IpAddr :: V4 ( nat_ip) => set_ipv4_mapping ( switch, nat_ip, low, high, tgt) ,
425+ IpAddr :: V6 ( nat_ip) => set_ipv6_mapping ( switch, nat_ip, low, high, tgt) ,
426+ }
427+ }
428+
416429pub fn set_ipv4_mapping (
417430 switch : & Switch ,
418431 nat_ip : Ipv4Addr ,
@@ -465,6 +478,18 @@ pub fn set_ipv4_mapping(
465478 }
466479}
467480
481+ pub fn clear_mapping (
482+ switch : & Switch ,
483+ nat_ip : IpAddr ,
484+ low : u16 ,
485+ high : u16 ,
486+ ) -> DpdResult < ( ) > {
487+ match nat_ip {
488+ IpAddr :: V4 ( nat_ip) => clear_ipv4_mapping ( switch, nat_ip, low, high) ,
489+ IpAddr :: V6 ( nat_ip) => clear_ipv6_mapping ( switch, nat_ip, low, high) ,
490+ }
491+ }
492+
468493/// Find the first `NatTarget` where its `Ipv4NatEntry` matches the provided
469494/// `Ipv4Addr` and overlaps with the provided port range, then remove it.
470495pub fn clear_ipv4_mapping (
@@ -502,9 +527,25 @@ pub fn clear_ipv4_mapping(
502527 Ok ( ( ) )
503528}
504529
530+ pub fn clear_overlapping_mappings (
531+ switch : & Switch ,
532+ nat_ip : IpAddr ,
533+ low : u16 ,
534+ high : u16 ,
535+ ) -> DpdResult < ( ) > {
536+ match nat_ip {
537+ IpAddr :: V4 ( nat_ip) => {
538+ clear_overlapping_mappings_v4 ( switch, nat_ip, low, high)
539+ }
540+ IpAddr :: V6 ( nat_ip) => {
541+ clear_overlapping_mappings_v6 ( switch, nat_ip, low, high)
542+ }
543+ }
544+ }
545+
505546/// Deletes any `Ipv4NatEntry` where each entry matches the provided
506547/// `Ipv4Addr` and overlaps with the provided port range
507- pub fn clear_overlapping_ipv4_mappings (
548+ pub fn clear_overlapping_mappings_v4 (
508549 switch : & Switch ,
509550 nat_ip : Ipv4Addr ,
510551 low : u16 ,
@@ -542,6 +583,44 @@ pub fn clear_overlapping_ipv4_mappings(
542583 Ok ( ( ) )
543584}
544585
586+ pub fn clear_overlapping_mappings_v6 (
587+ switch : & Switch ,
588+ nat_ip : Ipv6Addr ,
589+ low : u16 ,
590+ high : u16 ,
591+ ) -> DpdResult < ( ) > {
592+ let mut nat = switch. nat . lock ( ) . unwrap ( ) ;
593+ trace ! (
594+ switch. log,
595+ "clearing all nat entries overlapping with {}/{}-{}" , nat_ip, low, high
596+ ) ;
597+
598+ if let Some ( mappings) = nat. ipv6_mappings . get_mut ( & nat_ip) {
599+ let mut mappings_to_delete = find_mappings ( mappings, low, high) ;
600+ // delete starting with the last index first, or you'll end up shifting the
601+ // collection underneath you
602+ mappings_to_delete. reverse ( ) ;
603+ for idx in mappings_to_delete {
604+ let ent = mappings. remove ( idx) ;
605+ let full = ipv6_entry ( nat_ip, & ent) ;
606+ match nat:: delete_ipv6_entry ( switch, nat_ip, ent. low , ent. high ) {
607+ Err ( e) => {
608+ error ! ( switch. log, "failed to clear {}: {:?}" , full, e) ;
609+ return Err ( e) ;
610+ }
611+ _ => {
612+ debug ! ( switch. log, "cleared nat entry {}" , full) ;
613+ }
614+ } ;
615+ }
616+ if mappings. is_empty ( ) {
617+ nat. ipv6_mappings . remove ( & nat_ip) ;
618+ }
619+ }
620+
621+ Ok ( ( ) )
622+ }
623+
545624pub fn reset_ipv6 ( switch : & Switch ) -> DpdResult < ( ) > {
546625 let mut nat = switch. nat . lock ( ) . unwrap ( ) ;
547626
@@ -568,14 +647,14 @@ pub fn reset_ipv4(switch: &Switch) -> DpdResult<()> {
568647 }
569648}
570649
571- pub fn set_ipv4_nat_generation ( switch : & Switch , generation : i64 ) {
650+ pub fn set_nat_generation ( switch : & Switch , generation : i64 ) {
572651 let mut nat = switch. nat . lock ( ) . unwrap ( ) ;
573652
574653 debug ! ( switch. log, "setting nat generation" ) ;
575654 nat. ipv4_generation = generation;
576655}
577656
578- pub fn get_ipv4_nat_generation ( switch : & Switch ) -> i64 {
657+ pub fn get_nat_generation ( switch : & Switch ) -> i64 {
579658 let nat = switch. nat . lock ( ) . unwrap ( ) ;
580659
581660 debug ! ( switch. log, "fetching nat generation" ) ;
0 commit comments